我正在使用 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 如何输出添加按钮菜单元素的自定义名称。
答案 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;
}
}