4

I've got a custom class which can be edited through the PropertyGrid. In that class I've got a custom Collection (with custom PropertyDescriptor and TypeConverter).

Items can be added to or removed from the Collection with the default Collection Editor. This all works fine. But - after closing the Collection Editor, the PropertyGrid is not updated. When I manual make a call to Refresh() on the PropertyGrid, the changes are reflected in the PropertyGrid.

How can I get the PropertyGrid to automatically refresh when the Collection Editor has been closed? I sought for a solution earlier where I should subclass CollectionEditor (which I can't seem to find).

Please help.

MysticEarth
  • 2,646
  • 4
  • 33
  • 53

5 Answers5

2

RefreshPropertiesAttribute Class

Indicates that the property grid should refresh when the associated property value changes. This class cannot be inherited.

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

Adding Attribute with Descriptor

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

Walkthrough: Debugging Custom Windows Forms Controls at Design Time at http://msdn.microsoft.com/en-us/library/5ytx0z24.aspx

Community
  • 1
  • 1
AMissico
  • 21,470
  • 7
  • 78
  • 106
  • I've tried that and I doesn't work. When I add 1 item to the Collection when it's empty, the PropertyGrid gets updated. When I add another item, nothing happens until I manually refresh... – MysticEarth Jun 10 '10 at 12:44
  • I have had that happen before. The problem is in your classes. I suggest debugging the design-time of your control. – AMissico Jun 10 '10 at 12:48
  • I think it had something to do with the type-converter, convert-to, – AMissico Jun 10 '10 at 12:54
1

You might also try adding the NotifyParentProperty attribute to the collection. This has worked for me in similar situations.

Bill Brooks
  • 751
  • 1
  • 10
  • 30
1

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 just base your Collection editor on that. It will automatically refresh the property grid when the collection form is closed.

Be aware though, this solution is reflecting into the internals of the property grid and can be broken at any time, but i have done this for a while now with no problem

Steve Medley
  • 151
  • 3
  • 7
1

I get solution in this situation. There is a need to derive from CollectionEditor class and make custom editor like this:

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 main form I subscribe to 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();
    }

Regards, Artem

Artem
  • 11
  • 1
0

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;
        }
    }
}
mrhopehub
  • 1
  • 2