Sometimes, you need to bind to data that you don't know the structure of at design time, such as XML or JSON data. In this type of scenario, ideally, you'd be able to create an object at runtime that you could deserialize the data to and then bind to it. Silverlight 4 added support for dynamic types, which goes some way toward solving the issue. However, the downside to creating dynamic objects is that you can't actually bind to them, as Silverlight's binding engine doesn't recognize dynamic properties as real properties. Any attempt to bind directly to dynamic properties on objects will fail. To overcome this issue, Silverlight 5 introduced the ICustomTypeProvider
interface that you can implement on a class to tell the binding engine what the structure of the object is.
The ICustomTypeProvider
interface can be found in the System.Reflection
namespace and simply requires the implementation of a single method: GetCustomType
. However, the actual implementation of this method is unfortunately quite complex. You essentially need to create a type from scratch. The Type
class is unsealed in Silverlight 5, enabling you to inherit from it and override its properties and methods.
Rather than writing this ICustomTypeProvider
implementation yourself, Alexandra Rusina, a program manager in the Silverlight team at Microsoft, has created a helper class that will do the hard work for you, which you can download here: http://blogs.msdn.com/b/silverlight_sdk/archive/2011/04/26/binding-to-dynamic-properties-with-icustomtypeprovider-silverlight-5-beta.aspx
. Using this helper class, you can then create a class that either inherits from this helper class (the easiest method) or implements the ICustomTypeProvider
interface and delegates the GetCustomType
method to the helper class. Use the latter method if your class already inherits from another class.
For example, let's create a Product
class whose structure we'll define at runtime.
CustomTypeHelper
class:
public class Product : CustomTypeHelper<Product> { }
AddProperty
method that's been inherited from the CustomTypeHelper<T>
class, giving each property a name and a type:
Product.AddProperty("ProductName", typeof(string));
Product.AddProperty("Category", typeof(string));
Product.AddProperty("QtyAvailable", typeof(int));
SetPropertyValue
method on the Product
class (again, inherited from the CustomTypeHelper<T>
class), passing it the name of the property to set the value for, and its new value, like so:
Product product = new Product();
product.SetPropertyValue("ProductName", "Helmet");
product.SetPropertyValue("Category", "Accessories");
product.SetPropertyValue("QtyAvailable", 10);
INotifyPropertyChanged
interface, so you don't need to worry about that aspect. If necessary, you can get the property values in code using the GetPropertyValue
method that the Product
class has inherited from CustomTypeHelper<T>
:string productName = (string)product.GetPropertyValue("ProductName");
string category = (string)product.GetPropertyValue("Category");
int qtyAvailable = (int)product.GetPropertyValue("QtyAvailable");
Note Rather than write your own ICustomTypeProvider
implementation to wrap XML or JSON data from scratch, Matt Duffield has provided ICustomTypeProvider
implementations for these types of data that you may wish to try: http://mattduffield.wordpress.com/2011/09/16/using-icustomtypeprovider-in-silverlight-5-with-xml
.