如何在PropertyGrid自定义集合编辑器的“添加”按钮下拉列表中自定义名称

时间:2016-04-03 12:18:12

标签: c# editor propertygrid

我正在使用 PropertyGrid 来修改集合。具有该集合的对象定义如下:

class ObjWithCollection
{
    [Editor(typeof(MyCustomCollectionEditor),typeof(UITypeEditor))]
    public List<ItemBase> collection { get; set; } = new List<ItemBase>();//ItemBase is abstract
}

该集合包含两种类型的对象,派生自 ItemBase 类: Item1 Item2 。这些类定义如下:

public abstract class ItemBase
{
    public string Name { get; set; }
    public ItemBase() { }
    public ItemBase(string name) { Name = name; }
}

public class Item1:ItemBase
{
    public Item1():base("Item 1 name"){}
}

[DisplayName("item2 test display name")]
public class Item2:ItemBase
{
    public Item2() : base("item 2 name") { }
}

为了能够通过编辑器向集合添加新项目,我还定义了自定义集合编辑器类并覆盖 CreateNewItemTypes 以列出适合集合的所有类型:

class MyCustomCollectionEditor : CollectionEditor
{
    public MyCustomCollectionEditor(Type type) : base(type){}
    protected override Type[] CreateNewItemTypes()
    {
        return new Type[] { typeof(Item1), typeof(Item2) };
    }
}

然后我使用编辑器 attibute将我的自定义编辑器绑定到 ObjWithCollection.collection 属性(参见 ObjWithCollection.collection 定义)。

这很好用,我可以编辑我的收藏,包括添加新项目。 “添加”按钮有一个下拉列表,允许用户选择要添加的元素类型。 editor window http://i.share.pho.to/31d50d09_o.png

但是在添加按钮下拉列表中,项目名为“ Item1 ”和“ Item2 ”,我无法更改此名称。我尝试了 DisplayName 属性, ToString 覆盖,但没有运气。

所以, qustion 如何输出添加按钮菜单元素的自定义名称。

2 个答案:

答案 0 :(得分:3)

我认为这不可能直接来自属性网格的代码。但是,您可以使用TypeDelegator欺骗系统并强制它使用例如您的DisplayName属性,而不是默认情况下使用的类型的Name属性。

1)创建一个自定义TypeDelegator,如下所示:

class MyTypeDelegator : TypeDelegator
{
    public MyTypeDelegator(Type delegatingType)
        : base(delegatingType)
    {
    }

    public override string Name
    {
        get
        {
            var dna = (DisplayNameAttribute)typeImpl.GetCustomAttribute(typeof(DisplayNameAttribute));
            return dna != null ? dna.DisplayName : typeImpl.Name;
        }
    }
}

2)修改CreateNewItemTypes(),如下所示:

    protected override Type[] CreateNewItemTypes()
    {
        return new Type[] { new MyTypeDelegator(typeof(Item1)), new MyTypeDelegator(typeof(Item2)) };
    }

现在,您应该在菜单中看到显示名称而不是名称。

答案 1 :(得分:0)

您也可以通过挂钩到CollectionForm的控件来更改文本(丑陋,不推荐,不要在生产中使用,请注意它可以随时更改和废弃)

 public sealed class OutputItemEditor : CollectionEditor // need a reference to System.Design.dll
{
    public OutputItemEditor(Type type)
        : base(type)
    {
    }

    protected override Type[] CreateNewItemTypes()
    {
        return new[] { typeof(StaticOutputItem), typeof(VariableOutputItem),typeof(ExpressionOutputItem) };
    }

    protected override CollectionForm CreateCollectionForm()
    {
        CollectionForm collectionForm = base.CreateCollectionForm();            
        collectionForm.Text = "Output Collection";

        //Modify the Add Item Button Text
        try
        {
            //You can use "collectionForm.Controls.Find("addButton",true)" here also
            foreach (ToolStripItem item in collectionForm.Controls[0].Controls[1].Controls[0].ContextMenuStrip.Items)
            {
                //Since Item Names are the Type Names
                switch (item.Text)
                {
                    case "StaticOutputItem":
                        item.Text = "Static Output Item";
                        break;
                    case "VariableOutputItem":
                        item.Text = "Variable Output Item";
                        break;
                    case "ExpressionOutputItem":
                        item.Text = "Expression Output Item";
                        break;
                    default:
                        break;
                }
            }
        }
        catch (Exception)
        {
        }

        return collectionForm;
    }
}