Normally, the collection displays an ellipsis button, allowing the user to manipulate the collection, but does not allow the user to expand the list of items like an array does. I figured this would be very simple to add. The .NET framework provides a base class for an object called a TypeConverter. The TypeConverter allows objects of various types to be translated to and from various representations.
Beyond that, the TypeConverter can supply a list of standard values (Enumerators use this, which allows the property grid to display a drop-down list containing the various valid values.) The TypeConverter can also supply an editor class for the type (You see this in form designers all the time, the font dialog, the drop-down for colors, the drop-down for for docking, etc...) Finally, the type converter can also supply a list of properties that the object can display as child properties of a property. It is this that I will focus on:
The above code demonstrates how the properties are provided by the TypeDescriptor. Using the above code results in the following list in the grid:
Far from optimal for dealing with a list of items. The list is sorted alphabetically. But arrays seem to sort by index. That was what I wanted, so I began spelunking through the reference source code of the .NET framework. Examining the Array code and ArrayConverter code revealed nothing. They were doing essentially what I was doing. I then explored the grid. It appears the PropertyGrid itself considers an array a special case and sorts the items by index. That is no use to me.
Using the sort method of the PropertyDescriptorCollection object does nothing, since the grid will always override it with the user's sort preference. So, how to sort the items by index?
The secret is in the property descriptor collection. Replacing the return statement above with the following:
The following listing shows the ListPropertyDescriptorCollection class that does the magic:
The code that performs the trick should be rather self-evident:
Two lines of code in this function do all that is necessary to force the numeric sort. The comparer in this case compares the indicies of the descriptors, causing the sort function to sort by the numeric index. This completely replaces any sort function used with the desired sort, thereby forcing a sort by index.