dimanche 29 novembre 2009

CollectionView.GetItemProperties : Great and good differences between WPF 3.5 and 4.0

WPF 3.5 algorithm

In WPF 3.5, when you bind your own Collection to a wpf control, "WPF framework" needs define the list of all allowed properties of the items of the collection.

To do this, "WPF Framework" tests if collection is a generic type, AND if the generic type contains only one sub-type : it is use to define the item type of collection, in other case, "WPF Framework" try to use the first item of the collection (if collection is not empty)

With Reflector, you can find a part of this algorithm in CollectionView.GetItemType() :

internal Type GetItemType(bool useRepresentativeItem)
{
Type type = this.SourceCollection.GetType();
if (type.IsGenericType)
{
Type[] genericArguments = type.GetGenericArguments();
if (
genericArguments.Length == 1)
{
return
genericArguments[0];
}
}

else if (useRepresentativeItem)
{
object representativeItem = this.GetRepresentativeItem();
if (representativeItem != null)
{
return representativeItem.GetType();
}
}
return null;
}

in WPF 4.0 beta 2, Algorithm is different !!!!


WPF 4.0 beta 2 algorithm

in WPF 4.0, framework test if original collection source support a generic IEnumerable type and If test is True, the type of this subtype of Generic IEnumerable !


the code of this version is :

internal Type GetItemType(bool useRepresentativeItem)
{
foreach (Type type2 in this.SourceCollection.GetType().GetInterfaces())
{
if (
type2.Name == IEnumerableT)
{
Type[] genericArguments = type2.GetGenericArguments();
if (
genericArguments.Length == 1)
{
return
genericArguments[0];
}
}
}

if (useRepresentativeItem)
{
object representativeItem = this.GetRepresentativeItem();
if (representativeItem != null)
{
return representativeItem.GetType();
}
}
return null;
}

Consequences :

It is a very important change if you develop your own collection. With the new approach, It is possible now to create generic collection with more than one sub type !


for example, in MVVM architecture, it would be very nice to create a ViewModel of collection to enumerate ViewModel of item with a specific contraint


Exemple :


public class  ViewModelCollectionBase<TViewModel, TModel> : IEnumerable<TViewModel>
where TViewModel : ViewModelBase<TModel>
{
…  
}


public class ViewModelBase<TModel> where TModel : class
{

}