Saw this in the google searches today, this one is somewhat tricky. I haven't looked yet but I am hoping they have fixed this in .NET 2 with Template methods.
So, you have a class that you are displaying in either your own designer or at design time in Visual Studio. One of the properties on this class is a collection that contains members of a Type you have created. When you click the ellipses (...) button next to this property in the property grid, the designer Adds and Removes instances of System.Object in the collection, which is not very useful. Here's how I got this to work, with examples from the very neglected TRAP project:
First, instead of something like ArrayList for the type of the property containing the collection items, I created a class that implements CollectionBase, IList, ICollection. Take note of the class-level attributes
[Editor("DamonPayne.Trap.UI.PersistentPropertyEditor", "System.Drawing.Design.UITypeEditor") ] public class PersistentPropertyCollection : CollectionBase, IList, ICollection
then, these designer attributes on the property of this type:
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), Editor(typeof(PersistentPropertyEditor), typeof(System.Drawing.Design.UITypeEditor) ), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Description("Collection of Properties that are persisted to the data store") ] public PersistentPropertyCollection PersistentProperties { get{return _persisentProperties;} set{_persisentProperties = value;} }
Now, on the type contained within my PersistentPropertyCollection (PersistentProperty), I have the following designer attributes:
[TypeConverter(typeof(PersistentPropertyConverter)), EditorBrowsable(EditorBrowsableState.Always), Category("Misc"), ] public class PersistentProperty
The PersistentPropertyConverter is just a class that extends ExpandableObjectConverter and implments custom functionality. That part is not important for this example.
The final code snippet here is the most important part. When providing implemntations for some of the IList, etc members, I do not use the type Object but rather my own concrete type:
(...) public PersistentProperty this[int index] // Indexer {(...) public void Remove(PersistentProperty value) { _list.Remove(value); } public void Remove(object value) { _list.Remove(value); }(...) public int Add(PersistentProperty value) { return _list.Add(value); } public int Add(object value) { if (_list.Contains(value)) { return -1; } return _list.Add(value); } public void AddRange(PersistentProperty[] items) { foreach(PersistentProperty p in items) { Add(p); } }(...)
Notice that for some of these the methods are overloaded for type Object and my concrete type. The designer is able to figure it out, and voila, my custom collection editor for the TRAP gui looks like so:
I'll have to post more on .NET designer stuff when I get the chance.