This project has moved. For the latest updates, please go here.

Bind PropertyGrid.SelectedObject to IList<T>

Jan 30, 2012 at 9:48 AM

Hi all!
I would like to use the PropertyGrid as an editor for an IList<T>. Why would someone want things like that?
First of all, because PropertyGrid is a really, really great control and almost everyone is familiar with it!

To understand what I'm trying and why, I have to describe the project I'm working on: Actually it is a quite big solution consisting of multiple projects, some of them implemented in native C++ MFC = business logic. Most of those C++ projects and classes are wrapped using SWIG (www.swig.org) and are therefore visible and accessible from .NET. Because the native classes use MFCs data structures most of them inherit from CObject class. Furthermore this inheritance is exposed to .NET using SWIG, restricting any further inheritance in .NET to interfaces only. This fact cannot be changed.
Note: All native classes exposed to .NET can be easily extended by methods, fields, properties, etc. and they can also implement any interfaces desired.

There is one more important constraint that has to be considered: .NET shouldn't have any member fields pointing to any C++ objects, since there are multiple network listeners and other asynchronous threads running within the business logic. Thus C++ items could be added to or get removed from data structures exposed to .NET. That's why any references to C++ objects have to be reduced to the absolute minimum.

Now, the problem:

  • A native array of dynamic size, call it NativateArray, stores NativeItems and implements interfaces IList<NativeEntry> and IEnumerable<NativeItem>.
  • Each NativeItem is actually nothing more than a storage of a single member field and a title. For simplicity we can assume that the member field is numeric (i.e. a double) and the title is just an ordinary .NET string.
  • It would be really great to bind PropertyGrid.SelectedObject to an instance of NativeArray and to edit the NativeItems like properties.

My first guess was to implement an ICustomTypeDescriptor interface for the NativeArray and to generate a PropertyDescriptorCollection with PropertyDescriptors (one PropertyDescriptor for each item of the array). Thereby I generated property names like "Property_01" for an item stored at index 1 of the array.

It works out somehow, but .NET keeps reporting binding errors for properties "Property_XX" as they cannot be found on the NativeArray type. Also, it is not possible to display or edit values of properties simulated by PropertyDescriptors. Only titles and further things specified by (generated) attributes are shown correctly. I hoped that providing a PropertyDescriptor with GetValue() and SetValue() methods would render direct access/binding to the non-existent properties unnecessary. It seems like .NET wouldn't think so.

Option 1
If PropertyGrid could work with a kind of get and set methods they could be added to an existing type (i.e. NativeArray) at run-time using System.Reflection.Emit.DynamicMethod class.  Unfortunately there is no such option for properties, as properties can only be added to new (dynamic) classes using System.Reflection.Emit.PropertyBuilder.
Generating a new type/class at run-time to provide run-time-built properties for each item of a NativeArray would also mean to set and hold a reference to that instance of NativeArray (within the generated type in order for properties to access corresponding NativeItems). This reference might break at any time and is thus not desirable.

Option 2
Implement IDynamicMetaObjectProvider, IDictionary<string, object> and INotifyPropertyChanged interfaces for the NativeArray in the same way System.Dynamic.ExpandoObject class does. This way I could try to add properties at run time, hoping that PropertyGrid & WPF could handle them.

 

Are there any further ideas? Or any experience with ExpandoObjects and PropertyGrid?
Or should I try something completely different like DataGrid - which looks quite.. er bulky?

Thanks for your help!

Jan 31, 2012 at 2:44 PM

The PropertyGrid is not meant to support this scenario.  I would suggest using the CollectionEditor or the CollectionEditorDialog to edit a IList<T>

Jan 31, 2012 at 3:36 PM

Actually it seems to work with a reduced version of System.Dynamic.ExpandoObject.

I do not need nor use the implementation of an IDictionary<string, object> so I just left it out. Now my NativeArray implements ICustomTypeDescriptor, IDynamicMetaObjectProvider and INotifyPropertyChanged. Thus I can create a PropertyDescriptorCollection with PropertyDescriptors (one PropertyDescriptor for each NativeItem of the array) and in addition properties with names corresponding to those used for construction of PropertyDescriptors.

Till now I have only a proof-of-concept and not the full solution, but it looks quite promising.

Thanks again.

Jan 31, 2012 at 4:03 PM

Nice.  It is good to see how far you can push the PropertyGrid.  Let me know how it turns out.

Feb 8, 2012 at 7:35 AM

Finally, I can confirm the proposed solution (combining System.Dynamic.ExpandoObject with ICustomTypeDescriptor).
Even though it's quite a mess, it works just fine.