More specifically the behavior when the combobox editor is double clicked it changes its current item to the next one.
When using a the following property store item: this.PropertyStore.Add(typeof(Image) , "Test Image" , null ); the user cannot select an image via the BrowseEditor.
To reproduce: -add a RadPropertyGrid and use the following code: radPropertyGrid.SelectedObject = new MyPropertyGridAdapter(node); PropertyValueChanging += new PropertyGridItemValueChangingEventHandler(OnPropertyValueChanging); private void OnPropertyValueChanging(object sender, PropertyGridItemValueChangingEventArgs e) { var form = new CommentActionForm(); if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK) { var item = e.Item as PropertyGridItem; var pd = item.PropertyDescriptor as MyPropertyDescriptor; if (pd != null) { // Perform value change (affects database). } } else { e.Cancel = true; } } Workaround:when ending edit mode with Enter key you may use the following approach: public Form1() { InitializeComponent(); this.radPropertyGrid1.SelectedObject = new MyObject(10204, "Sample name", "Some descripion"); this.radPropertyGrid1.EditorRequired += radPropertyGrid1_EditorRequired; } private void radPropertyGrid1_EditorRequired(object sender, PropertyGridEditorRequiredEventArgs e) { PropertyGridItem propertyItem = e.Item as PropertyGridItem; e.Editor = new MyEditor(propertyItem); } public class MyObject { public int ID { get; set; } public string Name { get; set; } public string Description { get; set; } public MyObject(int iD, string name, string description) { this.ID = iD; this.Name = name; this.Description = description; } } public class MyEditor : PropertyGridTextBoxEditor { public string InitialValue { get; set; } public PropertyGridItem PropertyItem { get; set; } public MyEditor(PropertyGridItem item) : base() { this.PropertyItem = item; } public override void BeginEdit() { InitialValue = this.TextBoxEditorElement.Text; base.BeginEdit(); } } public class MyPropertyGrid : RadPropertyGrid { protected override bool ProcessDialogKey(Keys keyData) { if (this.ActiveEditor != null && this.ActiveEditor is MyEditor && keyData == Keys.Enter) { MyEditor editor = ((MyEditor)this.ActiveEditor); PropertyGridItem property = editor.PropertyItem; string initialValue = editor.InitialValue; DialogResult ds = RadMessageBox.Show("Are you sure?", "Title", MessageBoxButtons.OKCancel, RadMessageIcon.Question); if (ds == System.Windows.Forms.DialogResult.Cancel) { property.Value = initialValue; return false; } } return base.ProcessDialogKey(keyData); } }
FIX. RadPropertyGrid - setting the SelectedObject to something and then set it to a property store, does not remove the initial items Workaround: clear the items prior setting the property store: this.radPropertyGrid1.PropertyGridElement.PropertyTableElement.ListSource.Clear();
Steps to reproduce. 1. Drag a RadPropertyGrid to a form. 2. Set the selected object to a button for example. 3. Set the System.Threading.Thread.CurrentThread.CurrentUICulture to bg-BG for example 4. Run the project and try to edit the Size property. You will see that it is displayed in the format X;Y, but you have to enter string in the X,Y format otherwise you get an exception.
If one sets an empty RadPropertyStore to the SelectedObject property of a RadPropertyGrid and then adds items with a RadSortOrder attribute the items will still be sorted by their name. WORKAROUNDS: 1. Populate the store before you set it to the property grid. 2. Add a dummy item to the store before you set it to the property grid and then remove it: RadPropertyStore store = new RadPropertyStore(); store.Add(typeof(bool), "dummy", false); this.radPropertyGrid1.SelectedObject = store; store.RemoveAt(0); 3. After you add the first item to the store call the following method: this.radPropertyGrid1.PropertyGridElement.PropertyTableElement.ListSource.CollectionView.EnsureDescriptors();
When the SelectedObject contains sub-properties and a user expands a property the CreateItem event is not fired for sub items.
When a property has a TypeConverter and a UITypeEditor attributes the PropertyGridUITypeEditor calls the TypeConverter methods with the context parameter equal to null.
To reproduce: use a class with more than 100 properties for the RadPropertyGrid.SelectedObject. On RadButton.Click event set the RradPropertyGrid.PropertySort to PropertySort.CategorizedAlphabetical.
To reproduce: - Add a property grid to a blank form set the selected object the the same form. - Group the items and click several times to expand collapse the groups or items. - you will notice that some of expanded/collapsed groups icon is in wrong state (same applies for the +/- sign of the properties).
To reproduce: use the following code: Items _items = new Items(); public Form1() { InitializeComponent(); radPropertyGrid1.SelectedObject = _items; } class Items { [Description("A Bool Property")] public bool IsEnabled { get { return _isEnabled; } set { _isEnabled = value; RadMessageBox.Show("IsEnabled"); } } private bool _isEnabled; [Description("A String Property")] public string Name { get { return _name; } set { _name = value; RadMessageBox.Show("Name"); } } private string _name ; } Steps to perform: 1. Change the "Name" property and leave the editor active. 2. Click on the check box to change the "IsEnabled" property. As a result you will notice that the "IsEnabled" setter is called before the "Name" setter. Workaround: Items _items = new Items(); public Form1() { InitializeComponent(); this.radPropertyGrid1.CreateItemElement += radPropertyGrid1_CreateItemElement; radPropertyGrid1.SelectedObject = _items; } private void radPropertyGrid1_CreateItemElement(object sender, CreatePropertyGridItemElementEventArgs e) { if (e.ItemElementType == typeof(PropertyGridCheckBoxItemElement)) { e.ItemElementType = typeof(CustomPropertyGridCheckBoxItemElement); } } public class CustomPropertyGridCheckBoxItemElement : PropertyGridCheckBoxItemElement { public CustomPropertyGridCheckBoxItemElement() { this.CheckBoxElement.ToggleStateChanging += CheckBoxElement_ToggleStateChanging; } private void CheckBoxElement_ToggleStateChanging(object sender, StateChangingEventArgs args) { if (this.PropertyTableElement.ActiveEditor != null && this.PropertyTableElement.SelectedGridItem != this.Data) { this.PropertyTableElement.EndEdit(); } } protected override void DisposeManagedResources() { this.CheckBoxElement.ToggleStateChanging -= CheckBoxElement_ToggleStateChanging; base.DisposeManagedResources(); } }
Workaround: public class CustomPropertyGrid : RadPropertyGrid { public override string ThemeClassName { get { return typeof(RadPropertyGrid).FullName; } } protected override PropertyGridElement CreatePropertyGridElement() { return new CustomPropertyGridElement(); } } public class CustomPropertyGridElement : PropertyGridElement { protected override Type ThemeEffectiveType { get { return typeof(PropertyGridElement); } } protected override PropertyGridSplitElement CreateSplitElement() { return new CustomPropertyGridSplitElement(); } } public class CustomPropertyGridSplitElement : PropertyGridSplitElement { protected override Type ThemeEffectiveType { get { return typeof(PropertyGridSplitElement); } } protected override PropertyGridTableElement CreateTableElement() { return new CustomPropertyGridTableElement(); } } public class CustomPropertyGridTableElement:PropertyGridTableElement { protected override Type ThemeEffectiveType { get { return typeof(PropertyGridTableElement); } } public override bool ProcessKeyDown(KeyEventArgs e) { if (e.KeyData == Keys.Enter && ((PropertyGridItem)this.SelectedGridItem).PropertyType == typeof(bool)) { PropertyGridItem item = this.SelectedGridItem as PropertyGridItem; item.Value = !(bool)item.Value; return true; } return base.ProcessKeyDown(e); } }
To reproduce: Use the following code snippet and perform the step illustrating on the attached gif file. Note that this undesired behavior appears randomly. Partial Public Class Form1 Inherits Telerik.WinControls.UI.RadForm Public Sub New() InitializeComponent() radPropertyGrid1.PropertySort = Windows.Forms.PropertySort.Categorized radPropertyGrid1.SortOrder = Windows.Forms.SortOrder.None Dim metaDocItem As New PropertyStoreItem(GetType(String), "Document ID", "16.0", "Document ID Number", "Meta Data", True) Dim fileInfoItem As New PropertyStoreItem(GetType(FileInfo), "File Info", New FileInfo("sample file path", "file name path"), _ "", "Meta Data", True) fileInfoItem.Attributes.Add(New TypeConverterAttribute(GetType(MyDataConverter))) Dim stringItem As New PropertyStoreItem(GetType(String), "String", "telerik", "Property storing a string value", "Meta Data", True) Dim dockItem As New PropertyStoreItem(GetType(DockStyle), "Dock", DockStyle.Top, "Property containing DockStyle value", "Meta Data", True) Dim store As New RadPropertyStore store.Add(metaDocItem) store.Add(fileInfoItem) store.Add(stringItem) store.Add(dockItem) Me.RadPropertyGrid1.SelectedObject = store End Sub End Class Public Class FileInfo Private _filePath As String Private _fileName As String Public Sub New(filePath As String, fileName As String) Me._filePath = filePath Me._fileName = fileName End Sub Public ReadOnly Property FilePath() As String Get Return _filePath End Get End Property Public ReadOnly Property FileName() As String Get Return _fileName End Get End Property End Class Public Class MyDataConverter Inherits ExpandableObjectConverter Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean If destinationType = GetType(String) Then Return True End If Return MyBase.CanConvertTo(context, destinationType) End Function Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, _ value As Object, destinationType As Type) As Object If destinationType <> GetType(String) Then Return MyBase.ConvertTo(context, culture, value, destinationType) End If Return String.Empty End Function End Class Workaround: add a RadSortOrderAttribute to each PropertyStoreItem and leave the default SortOrder = Windows.Forms.SortOrder.Ascending
To reproduce: public Form1() { InitializeComponent(); this.radPropertyGrid1.SelectedObject = this; this.radPropertyGrid1.ContextMenuOpening += radPropertyGrid1_ContextMenuOpening; } private void radPropertyGrid1_ContextMenuOpening(object sender, Telerik.WinControls.UI.PropertyGridContextMenuOpeningEventArgs e) { foreach (RadItem item in e.Menu.Items) { if (item.Text == "Sort") { item.Visibility = ElementVisibility.Collapsed; item.PropertyChanged += item_PropertyChanged; } } } Workaround: private void radPropertyGrid1_ContextMenuOpening(object sender, Telerik.WinControls.UI.PropertyGridContextMenuOpeningEventArgs e) { RadItem item = null; for (int i = 0; i < e.Menu.Items.Count; i++) { item = e.Menu.Items[i]; if (item.Text=="Sort") { e.Menu.Items.Remove(item); } } }
The incorrect behavior is also observed if the SelectedObject is changed. How to reproduce: public partial class RadForm1 : RadForm { public RadForm1() { this.InitializeComponent(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.radPropertyGrid1.EnableSorting = true; this.radPropertyGrid1.SelectedObject = new TestObject(); foreach (var item in this.radPropertyGrid1.Items) { if (item.Name == "A") { item.SortOrder = 2; } else if (item.Name == "B") { item.SortOrder = 1; } else { item.SortOrder = 0; } } this.radPropertyGrid1.PropertySort = PropertySort.NoSort; } } public class TestObject { public int A { get; set; } public int C { get; set; } public int B { get; set; } } Workaround: 1. Use attributes in the model class: public class TestObject { [RadSortOrder(2)] public int A { get; set; } [RadSortOrder(0)] public int C { get; set; } [RadSortOrder(1)] public int B { get; set; } } 2. Alternatively, toggle the PropertySort property in the Shown event of the form: public partial class RadForm1 : RadForm { public RadForm1() { this.InitializeComponent(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.radPropertyGrid1.EnableSorting = true; this.radPropertyGrid1.SelectedObject = new TestObject(); foreach (var item in this.radPropertyGrid1.Items) { if (item.Name == "A") { item.SortOrder = 2; } else if (item.Name == "B") { item.SortOrder = 1; } else { item.SortOrder = 0; } } this.radPropertyGrid1.PropertySort = PropertySort.NoSort; } protected override void OnShown(EventArgs e) { base.OnShown(e); this.radPropertyGrid1.PropertySort = PropertySort.Alphabetical; this.radPropertyGrid1.PropertySort = PropertySort.NoSort; } } public class TestObject { public int A { get; set; } public int C { get; set; } public int B { get; set; } }
To reproduce: use the following code snippet and refer to the attached gif file. public Form1() { InitializeComponent(); this.radPropertyGrid1.SelectedObject = this; this.radPropertyGrid1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; } Workaround: public Form1() { InitializeComponent(); this.radPropertyGrid1.CreateItemElement += radPropertyGrid1_CreateItemElement; this.radPropertyGrid1.SelectedObject = this; this.radPropertyGrid1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; } private void radPropertyGrid1_CreateItemElement(object sender, CreatePropertyGridItemElementEventArgs e) { if (e.ItemElementType == typeof(PropertyGridItemElement)) { e.ItemElementType = typeof(CustomPropertyGridItemElement); } } public class CustomPropertyGridItemElement : PropertyGridItemElement { private bool isResizing; private Point downLocation; private int downWidth; protected override Type ThemeEffectiveType { get { return typeof(PropertyGridItemElement); } } private const int resizePointerOffset = 3; public override bool IsInResizeLocation(Point location) { return (location.X >= this.ControlBoundingRectangle.X + this.PropertyTableElement.ValueColumnWidth - resizePointerOffset && location.X <= this.ControlBoundingRectangle.X + this.PropertyTableElement.ValueColumnWidth + resizePointerOffset); } protected override void OnMouseDown(MouseEventArgs e) { if (IsInResizeLocation(e.Location)) { if (this.PropertyTableElement.IsEditing) { this.PropertyTableElement.EndEdit(); } this.Capture = true; this.isResizing = true; this.downLocation = e.Location; this.downWidth = this.PropertyTableElement.ValueColumnWidth; } base.OnMouseDown(e); } protected override void OnMouseMove(MouseEventArgs e) { if (this.isResizing) { int delta = e.Location.X - downLocation.X; if (this.RightToLeft) { delta *= -1; } this.PropertyTableElement.ValueColumnWidth = downWidth - delta; return; } if (this.IsInResizeLocation(e.Location)) { this.ElementTree.Control.Cursor = Cursors.VSplit; } else { this.ElementTree.Control.Cursor = Cursors.Default; } base.OnMouseMove(e); } protected override void OnMouseUp(MouseEventArgs e) { if (this.isResizing) { this.isResizing = false; this.Capture = false; } base.OnMouseUp(e); } }
Until the new feature is officially released please use the implementation in the attached project.