如何在 'CollectionEditor' 对话框中启用属性的默认值

How to enable Default Values for properties in a 'CollectionEditor' dialog

请先阅读整个问题以了解哪里我可以重置属性的默认值。

当定义一个可以可视化设计的自定义class时,可以实现一个collections编辑器来修改列表、数组、collections等属性,使用如下图案:

[Editor(typeof(CollectionEditor), typeof(UITypeEditor)),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ElementCollection Elements
{
    get;
}

编辑此 class 的 Elements 属性 现在将启动一个 CollectionEditor 对话框,左侧是成员列表,PropertyGrid在右边。

问题是,此 属性 网格似乎禁用了上下文菜单。 因此,我无法右键单击 属性 以 'reset' 它的默认值,尽管定义了 [DefaultValue] 属性。

然而,DefaultValue 属性被识别,因为 属性 没有序列化(并且在网格中以未加粗的文本正确显示)。

我想知道如何在 CollectionEditor 对话框的 PropertyGrid 上启用 这个上下文菜单

或者,可以实施的任何方式(热键,)能够重置这些collection项目属性。

您可以创建自己的 collection 继承 CollectionEditor class and then override CreateCollectionForm method, find property grid in the collection editor form and then register a ContextMenuStrip containing a Reset menu item for property grid, then reset the property using ResetSelectedProperty 的编辑器:

public class MyCollectionEditor : CollectionEditor
{
    public MyCollectionEditor() : base(typeof(Collection<MyElement>)) { }
    protected override CollectionForm CreateCollectionForm()
    {
        var form = base.CreateCollectionForm();
        var grid = form.Controls.Find("propertyBrowser", true).First() as PropertyGrid;
        var menu = new ContextMenuStrip();
        menu.Items.Add("Reset", null, (s, e) => { grid.ResetSelectedProperty(); });
        //Enable or disable Reset menu based on selected property
        menu.Opening += (s, e) =>
        {
            if (grid.SelectedGridItem != null && grid.SelectedObject != null &&
                grid.SelectedGridItem.PropertyDescriptor.CanResetValue(null))
                menu.Items[0].Enabled = true;
            else
                menu.Items[0].Enabled = false;
        };
        grid.ContextMenuStrip = menu;
        return form;
    }
}

然后这样装饰你的 collection 属性:

[Editor(typeof(MyCollectionEditor), typeof(UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Collection<MyElement> MyElements { get; private set; }

按照这种方法,您可以简单地添加分隔符、命令和描述菜单。