C # Winforms: PropertyGrid is not updated when an item is added to the collection

I have a custom class that can be edited using the PropertyGrid . In this class, I have a custom Collection (with custom PropertyDescriptor and TypeConverter ).

Items can be added or removed from Collection using the default collection editor. All of this works great. But after closing the collection editor, the PropertyGrid is not updated. When I find the Refresh() call on the PropertyGrid , the changes are reflected in the PropertyGrid.

How can I get the PropertyGrid to automatically update when the collection editor is closed? I used to look for a solution where there was a subclass of CollectionEditor (which I cannot find).

Please, help.

+4
source share
5 answers

RefreshPropertiesAttribute Class

Indicates that the property grid should be updated when a related change in property value. This class cannot be inherited.

Insert from http://msdn.microsoft.com/en-us/library/system.componentmodel.refreshpropertiesattribute.aspx

Adding an attribute with a handle

  Public Overrides ReadOnly Property Attributes() As System.ComponentModel.AttributeCollection Get Return New AttributeCollection(New Attribute() {RefreshPropertiesAttribute.Repaint}) End Get End Property 

Walkthrough Debugging Windows Forms user controls during development http://msdn.microsoft.com/en-us/library/5ytx0z24.aspx

+1
source

You can also try adding the NotifyParentProperty attribute to the collection. It worked for me in similar situations.

+1
source

I get a solution in this situation. There is a need to get the CollectionEditor class and create a custom editor as follows:

 public class MeasuredParamEditor : CollectionEditor { public static EventHandler CollectionChanged; public MeasuredParamEditor(Type type) : base(type) { } protected override string GetDisplayText(object value) { if (value is MeasuredParam) { MeasuredParam param = (MeasuredParam)value; return string.Format("{0}: {1}", param.Name, param.Value); } else return base.GetDisplayText(value); } protected override CollectionForm CreateCollectionForm() { CollectionForm collectionForm = base.CreateCollectionForm(); Form frm = collectionForm as Form; if (frm != null) { // Get OK button of the Collection Editor... Button button = frm.AcceptButton as Button; // Handle click event of the button button.Click += new EventHandler(OnCollectionChanged); } return collectionForm; } void OnCollectionChanged(object sender, EventArgs e) { if (CollectionChanged != null) { CollectionChanged(sender, e); } } } 

In the main form, I subscribe to the static event of my custom editor.

  private void MainForm_Load(object sender, EventArgs e) { MeasuredParamEditor.CollectionChanged += new EventHandler(OnMeasuredParamsChanged); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { MeasuredParamEditor.CollectionChanged -= new EventHandler(OnMeasuredParamsChanged); } void OnMeasuredParamsChanged(object sender, EventArgs e) { this.myPropGrid.Refresh(); } 

best regards, Artem

+1
source

I use this base class

 public class CollectionEditorBase : CollectionEditor { protected PropertyGrid ownerGrid; public CollectionEditorBase(Type type) : base(type) { } public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { PropertyInfo ownerGridProperty = provider.GetType().GetProperty("OwnerGrid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); ownerGrid = (PropertyGrid)ownerGridProperty.GetValue(provider); return base.EditValue(context, provider, value); } protected override CollectionForm CreateCollectionForm() { CollectionForm cf = base.CreateCollectionForm(); cf.FormClosing += delegate(object sender, FormClosingEventArgs e) { ownerGrid.Refresh(); if (CollectionEditorClosed != null) CollectionEditorClosed(this, value); }; return cf; } } 

Then you simply create the Collection editor. It will automatically update the property grid when the collection form is closed.

Remember that this decision reflects on the inside of the property grid and can be broken at any time, but I did it for a while without problems

+1
source

perfect solution

 using System; using System.ComponentModel.Design; using System.Windows.Forms; using System.Drawing.Design; using System.Collections; using System.ComponentModel; namespace ppgExpandableList { public class ExpandableListEditor : CollectionEditor { public ExpandableListEditor(Type type) : base(type){} public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value) { object editedValue = base.EditValue(context, provider, value); IList tmpList = (IList)editedValue; object tmpValue = Activator.CreateInstance(value.GetType()); IList editedList = (IList)tmpValue; foreach (object item in tmpList) { editedList.Add(item); } return editedList; } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } } } 
0
source

Source: https://habr.com/ru/post/1312434/


All Articles