This is a complex area; the following is a breakdown from winforms binding, but I understand that WPF binding isn't that different;
- given an object, the first thing binding code will do is look for
IListSource
- and if so use GetList()
to get the actual binding (this is how a data-table becomes a data-view for binding purposes)
- after that, the source is typically checked for
ITypedList
; this acts as a flexible way of obtaining pseudo-properties (GetItemProperties()
) represented by the model; data-view implements ITypedList
, creating pseudo-properties per instance
- otherwise, it might be possible to identify an obvious type for the data, which can mean:
- looking for an indexer of the form
public SomeType this[int index] {get;}
- note that most collections will satisfy this
- (not done by winforms, but might be for WPF) resolving via reflection the
T
in either IList<T>
or IEnumerable<T>
if the object implements those interfaces
- taking the first object (if any) from the sorce, and using
GetType()
- once a type is known,
TypeDescriptor.GetProperties(type)
can be used to obtain properties; in many cases this will be via reflection, but it is also possible to add an indirection layer (via TypeDescriptionProvider
) to supply properties for a type (this can be added at runtime, which can be very convenient)
- in the case of individual binding (not list binding), there is also
TypeDescriptor.GetProperties(obj)
- in addition to reflection and TypeDescriptionProvider
, this also has support for ICustomTypeDescriptor
which can be implemented by an individual object to supply custom properties at runtime (very similar to TypeDescriptionProvider
, but with the individual object taking responsibility for the properties)
I don't know exactly how much of this applies to WPF binding, but I'm pretty sure the IListSource
and ITypedList
processing is identical. From memory, most (all?) of the winforms strategies will work on WPF - so it could be that and changes are additional hooks.