C# Winforms:将项目添加到集合时 PropertyGrid 未更新

发布于 2024-09-04 17:06:40 字数 420 浏览 5 评论 0原文

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

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

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

请帮忙。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

仅此而已 2024-09-11 17:06:40

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

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

因为看清所以看轻 2024-09-11 17:06:40

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

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

爱要勇敢去追 2024-09-11 17:06:40

在这种情况下我得到解决方案。
需要从 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();
    }

问候, 阿尔乔姆

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

忆梦 2024-09-11 17:06:40

我使用这个基类

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

然后你只需将你的集合编辑器基于它即可。当收集表单关闭时,它会自动刷新属性网格。

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

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

遗失的美好 2024-09-11 17:06:40

完美解决方案

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

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;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文