C#Winforms:当项目添加到Collection时,PropertyGrid不会更新

时间:2010-06-10 12:25:00

标签: c# collections propertygrid

我有一个可以通过PropertyGrid编辑的自定义类。在该课程中,我有一个自定义Collection(自定义PropertyDescriptorTypeConverter)。

可以使用默认的Collection Editor在Collection中添加或删除项目。一切正常。但是 - 关闭集合编辑器后,PropertyGrid不会更新。当我手动拨打Refresh()上的PropertyGrid时,更改会反映在PropertyGrid中。

如何在关闭集合编辑器时让PropertyGrid自动刷新?我之前寻求一个解决方案,我应该将CollectionEditor子类化(我似乎无法找到)。

请帮忙。

5 个答案:

答案 0 :(得分:1)

  

RefreshPropertiesAttribute类

     

表示属性网格   应该在关联时刷新   财产价值变化。这个班   不能继承。

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

插入

使用描述符添加属性

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

演练:在设计时调试自定义Windows窗体控件 http://msdn.microsoft.com/en-us/library/5ytx0z24.aspx

答案 1 :(得分:1)

您也可以尝试将NotifyParentProperty属性添加到集合中。这在类似的情况下对我有用。

答案 2 :(得分:1)

我在这种情况下得到解决方案。 需要派生自CollectionEditor类并制作如下自定义编辑器:

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);
        }
    }
}

在主窗体中,我订阅了自定义编辑器的静态事件。

    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();
    }

问候,Artem

答案 3 :(得分:1)

我使用这个基类

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;
    }
}

然后你只需将你的收藏编辑器作为基础。收集表单关闭时,它将自动刷新属性网格。

请注意,这个解决方案反映在属性网格的内部,可以随时打破,但我已经做了一段时间了,没有问题

答案 4 :(得分:0)

完美解决方案

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;
        }
    }
}