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.
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.