WPF 4.5 – Part 13 : binding to types that Implement ICustomTypeProvider

, , 7 Comments

This is the part number 13 of the serie on the WPF 4.5 new features.

ICustomTypeProvider is an interface already known in the Silverlight 5 world but it is shipped with full support in WPF 4.5 too.

In this post we will discover what is the interface ICustomTypeProvider and how it can be used in WPF 4.5 !

ICustomTypeProvider : what is it ?

You may already know the ICustomTypeDescriptor (notice the ‘Descriptor‘ instead of the ‘Provider‘) interface as you are all WPF fans :-p ! This interface let you decide what information your type will expose when reflection is used.

Binding uses reflection… So by implementing this interface you can define a set of dynamic properties and create binding targeting them. This is particulary useful when you are building a framework or when you know the properties name only at runtime.

ICustomTypeProvider is basically the same thing but it is lighter and designed for Silverlight at start.

As this subject is covered since a long time for Silverlight 5, I won’t go in details on it. If you want more information you can read these helpful posts:

The thing to read in this post is that there is an helper class which helps you to create dynamic types. You can find an updated version of Alexandra’s one on Matthieu’s blog.

Make it work for WPF 4.5

The helper class does not works out of the box for WPF. Some pieces are actually missing for it to work 🙂 but the fixes are not too hard to implement.
First of all, you must override the CustomType.TypeHandle property to return the correct TypeHandle :
[csharp]public override RuntimeTypeHandle TypeHandle
{
get { return _baseType.TypeHandle; }
}
[/csharp]
If you want to discover what is this struct RuntimeHandle and its purpose, read this post from Vance Morisson.

Then you have to override the GetGetMethod and GetSetMethod of the CustomPropertyInfoHelper class. For this you’ll need the type o containing the property(I provide it trough the constructor). This can be done quick and dirty like this:
[csharp] public override MethodInfo GetGetMethod(bool nonPublic)
{
Action<object> getMethod = (object obj) =>
_fatherType.GetMethod("GetPropertyValue")
.Invoke(obj, new[] { _name });
return getMethod.Method;
}

public override MethodInfo GetSetMethod(bool nonPublic)
{
Action<object, object> setMethod = (object obj, object value) =>
_fatherType.GetMethod("SetPropertyValue")
.Invoke(obj, new[] { _name, value });
return setMethod.Method;
}
[/csharp]

How do I use it in my WPF app ?

With the helper you can create types dynamically. In the demo project on my dropbox folder (registration link), I create a class named ‘MyNewClass’ and add a property ‘Name’ to it in a static constructor.
[csharp] public class MyNewClass : CustomTypeHelper<MyNewClass>
{
static MyNewClass()
{
CustomTypeHelper<MyNewClass>.AddProperty("Name", typeof(string));
}

public MyNewClass(string p)
{
SetPropertyValue("Name", p);
}
}
[/csharp]

Once this is done, I can use it in a ViewModel to create a collection of this type:
[csharp] var classes = new ObservableCollection<MyNewClass>();
for (int i = 0; i < 50; i++)
{
classes.Add(new MyNewClass(string.Format("Person {0:##}", (1 + i))));
}
MyNewClasses = classes;
[/csharp]

Then, I can create binding on the dynamic property Name in my XAML:
[xml]<DataTemplate x:Key="PersonDataTemplate" DataType="model:Person">
<Border>
<TextBlock Text="{Binding Name}"/>
</Border>
</DataTemplate>

<!– More xaml code –>
<ListBox ItemsSource="{Binding MyNewClasses}"
ItemTemplate="{StaticResource PersonDataTemplate}"
HorizontalContentAlignment="Stretch" />
[/xml]

It works like a charm 🙂

 

7 Responses

  1. Thomas Levesque

    25/11/2011 2 h 50 min

    That’s cool, but I don’t really understand how this is different from ICustomTypeDescriptor, and it seems more difficult to use. I mean, you can already create a similar helper base class that implements ICustomTypeDescriptor, and it’s much easier! But perhaps I’m missing something?

  2. Thomas Levesque

    25/11/2011 2 h 52 min

    BTW, ICustomTypeDescriptor doesn’t change what reflection sees; it’s only involved when you examine an object with the TypeDescriptor class.

Comments are closed.