A Reader Question on DataBinding
This one asks how to handle Properties of embedded objects.Question:
Bill,
After reading your paper on Visual Studio Magazine, I spent a few hours trying to bind to a subproperty and... I'm wondering if it is possible!
I first coded a ContactList class, a collection of Contact. ContactList is setup as your AddressList so I can use it as a component and bind my UI to it. Nice!
I then added an Addresses property - of type AddressList - to the Contact class. This enabled me to select contactList1 as DataSource and contactList1.Addresses as DataMember in the properties box for a DataGrid. Very nice!
Then I added a Phone property to the Contact class. Phone has type PhoneNumber, a custom class with 2 properties AreaCode and Number. My goal was to use the properties box to bind the Text property of a TextBox control (WinForms) to contactList1.PhoneNumber.AreaCode (in section Data/DataBindings/text of the properties box). But I missed something. I can't managed to have the PhoneNumber property to "expand" in the properties box. I've tried to use differents attributes for AreaCode and Phone properties. I also searched for an interface similar to ITypedList or IListSource, but for a single instance, not a list.
Do you have any idea on how to do it?
Anyway, thank you for the great value paper!
Answer:
Like almost everything, there is more than one answer. The simple answer is that you can modify your Contact class to contain properties for the phone number fields: AreaCode and PhoneNumber. These would simply delegate the work to the contained Phone object.
The other answer might be more elegant, but it is quite a bit more work. The Contact class must support the ICustomTypeDescriptor interface. The key method for your example is ICustomTypeDescriptor.GetProperties(). This method returns a collection of PropertyDescriptor objects, or objects of a class that derives from PropertyDescriptor. A PropertyDescriptor contains information on the name of the property, and can access the property’s Get and Set methods. In your example the name would be something like “PhoneAreaCode”, or “PhoneNumber”. The PropertyDescriptor’s “GetValue” method returns the value of the Phone objects Number property, by going through the Contact and Phone objects. There is a similar “SetValue” property, that sets the value of a named property by going through the Contact and Phone objects.
Incidentally, DataRowView supports the ICustomTypeDescriptor interface to provide the support for named columns in a typed dataset. That implementation uses reflection to determine what columns and relationships are available on a particular dataset. Those are exposed through the designer. At runtime, the same implementation handles the get and set methods for columns in each DataTable. Otherwise, the databinding libraries would not work with indexers, as used to access individual cells in the DataSet.
The original referenced articlePublished June 2003 on Fawcette.com