问题
I'm using PropertyGrid to edit a collection. An object with the collection is defined as following:
class ObjWithCollection
{
[Editor(typeof(MyCustomCollectionEditor),typeof(UITypeEditor))]
public List<ItemBase> collection { get; set; } = new List<ItemBase>();//ItemBase is abstract
}
The collection contains the objects of two types, derived from ItemBase class: Item1 and Item2. These classes defined as following:
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") { }
}
To be able to add new items to the collection via the editor, I also defined the custom collection editor class and override CreateNewItemTypes to list all types suitable for collection:
class MyCustomCollectionEditor : CollectionEditor
{
public MyCustomCollectionEditor(Type type) : base(type){}
protected override Type[] CreateNewItemTypes()
{
return new Type[] { typeof(Item1), typeof(Item2) };
}
}
Then I bind my custom editor to the ObjWithCollection.collection property with Editor attibute (see ObjWithCollection.collection definition).
This works fine and I able to edit my collection, including the adding of the new items. The Add button has a dropdown which allows user to select the type of element to add. editor window http://i.share.pho.to/31d50d09_o.png
But in the Add button dropdown the items called "Item1" and "Item2" and I can't change this names. I tried DisplayName attribute, ToString override, but no luck.
So, the qustion is how to I can output the custom names for the elements of the Add button menu.
回答1:
I don't think this is possible directly from the property grid's code. However, you can use a TypeDelegator to trick the system and force it to use for example your DisplayName attribute in lieu of the type's Name property it uses by default.
1) create a custom TypeDelegator, like this:
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) modify CreateNewItemTypes() like this:
protected override Type[] CreateNewItemTypes()
{
return new Type[] { new MyTypeDelegator(typeof(Item1)), new MyTypeDelegator(typeof(Item2)) };
}
Now, you should see the display names instead of the name in the menu.
回答2:
You can also change the text by hooking into CollectionForm's Controls (Ugly, Not Recommended, DO NOT USE IN PRODUCTION, Note that it could be changed and obsolete in anytime)
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;
}
}
来源:https://stackoverflow.com/questions/36385305/how-to-customize-names-in-add-button-dropdown-in-the-propertygrid-custom-colle