views:

214

answers:

1

I have a helper class that implements ITypedList, to provide objects for databinding against custom collections.

My implementation allows me to easily specify that I want sub-properties of objects to be available for data binding, for instance I can bind to "Id", "Name", and also "Children.Count".

Now, my problem now is that in order to provide helper-objects to data-bind to such columns, I need to pre-populate a collection with those objects, and then later on when a grid asks for such helper objects through the interface, it will call a method on my object to retrieve them.

The method it calls has a parameter that can be used to specify which accessor objects to retrieve, but it's invariably null for the .NET DataGridView class, which means I just have to return all the objects I got.

So my question is this. Is there an alternative to ITypedList that I can implement where I will be told explicitly which properties the grid is interested in, so that I don't have to pre-populate the collection of acccessor objects?

Here's what my code looks like now:

var wrapper = new TypedListWrapper<Person>(someNormalCollectionClass);
wrapper.BindableProperties = "Id;Name;Children.Count";
grid.DataSource = wrapper;

here's what I want it to look like:

grid.DataSource = new TypedListWrapper<Person>(someNormalCollectionClass);

Any takers?

+3  A: 

If you were to create your own grid, then of course you could implement functionality like this, but not with the DataGridView (or, I would imagine, any current third-party grid control). I would also be wary of the design-time constraints this would place. If PropertyDescriptor initialization is what's causing your concern, then I would suggest loading up the individual PropertyDescriptor objects with just a name and a type and have actual usage of the object cause it to load any other information that might be required.

In general, though, these should be inexpensive operations. If you're having performance anxiety over your ability to obtain the list of properties in a reasonable amount of time, you may need to examine where the bottleneck is in your architecture and try to find a way around it. Apart from that, though, I don't see an option for you. The databinding system is, by design, consumer agnostic. There is no means for a binding consumer to indicate whether or not he intends to use a descriptor or not. Having something like that would be a real chicken-or-the-egg headache.

Adam Robinson
The problem is not the usage of the objects, it's basically how many should I add. I could add all the properties on the object that I add to the list, but then what about properties that themselves return objects, should I add all those? And what about properties on those that return objects? Where should I stop?
Lasse V. Karlsen
Nice answer Adam, but can you clarify something for me? In the signature `ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)`, what is the purpose of the `listAccessors` argument? In my implementations, I've ignored it and returned all properties I want to expose, but it seems as though the intention of this argument was for a consumer to specify what properties they are actually interested in. The docs say: _An array of System.ComponentModel.PropertyDescriptor objects to find in the collection as bindable. This can be null._
Drew Noakes
@Drew: I couldn't tell you. While I haven't done exhaustive research, I've never seen anyone use them (and, if I recall correctly, the DataView class ignores this as well, but don't quote me on that).
Adam Robinson
@Lasse: I think the quandry you're facing is the reason that deep inspection wasn't a part of the data binding system...there's too much room for error and too much room for performance degradation as you navigate down. I've always found it easier to create a wrapper class that's used for binding where I expose properties that may navigate down. This eliminates the need for defining "how far" in any abstract way; you have complete control and it's (usually) a simple implementation.
Adam Robinson