Jul 17 2011

Creating Design Data for XAML using a dynamics wrapped in a static class with a fluid interface.

Category: mvvm | wpfAdministrator @ 22:48

Why and How

Having design data while designing a user interface in Visual Studio or Blend is great. Designing multi-level ItemTemplates without design time data is like trying to paint in the dark.


But sometimes I struggle getting my actual ViewModels to work as design data. They have too many dependencies and I don’t want to clutter my production code with functionality that is only there to make my objects have the extra purpose of being Design Time friendly.


I wanted to mock some quick objects. So, I started using dynamics with the ExpandoObject in .NET 4 to create a quick object that I would use in Design Time like this:

 

I know my ViewModel has a property named “Name” and some City objects in a Cities collection. With a dynamic object, I can just duck-type away until I have enough to enable me to see what I’m doing  while designing the user interfarce.


The ExpandoObject inherits from DynamicObject. A DynamicObject will accept any method or property and just “try” to figure out what to do at runtime. It has methods like “TryInvokeMember” so if someone tries to call a member on it that does not exist, it can decide what to do at runtime.


I then created my own version of the dynamic ExpandoObject  and wrapped it in a static class to make it easy to use. Ease of use my top priority for creating Design Time data. I added methods on the static class that would create properties, collections and child objects on the dynamic object. Most of the methods returns the same object to enable a fluent programming interface.


Now You can write something like this to create design time data:

You start by creating a DesignData object. Adding properties to the object is done with the .Property() method. The .Property() method returns itself to allow you to continue adding. Adding a Child object simply adds a new DesignData object as a property and returns the new DesignData object that you continue adding properties children or collections to.

Adding collections (to mock your Observable Collections in the real ViewModels) is done by using the .Collection() method. It accepts a number (or range) of objects that you with to create and can either “yield return” an IEnumerable to let you foreach over the created items in the collection (in order to add Properties to them) or you can specify a Delegate Action of DesignData to enable a lambda expression syntax with anonymous methods.

The .Property method allows you to specify up to 10 pieces of design data that will randomly be used. The properties are Objects so you are not limited to strings. You can use ints, true/false, images or what ever you like.

You don't have to understand how it works to use it! The great thing about this is that it is totally separated from your runtime code so you can't shoot yourself in the foot and will not add complexity or bugs to your runtime code.

Setting it up

1)    Add the DesignData class to your project. (download the class here)

2)    Add the DesignDataLocator class to your project. (download example here)

3)    Add a reference to the DesignDataLocator in your App Resources.

 

4)    In the DesignDataLocator class, add a property for each ViewModel you wish to mock and let it return the .Output property of a DesignData object.

5)    In your xaml, Add a reference to that property in the DesignDataLocator as the design DataContext.

 

Now you can add properties, children and collections to your fake ViewModel and see what you are doing in Blend and Visual Studio.


Please note that this does not work in Silverlight because Silverlight will not let you bind to dynamic objects from Xaml. But Silverlight 5 has an ICustomTypeProvider interface that I will try to use to enable the exact same behavior when I get time to play with that.

Demo Project

I created a little demo-project for you. It uses the above demo-data and it is hooked up to a window that displays the data in nested ItemsControls like this:

 

This is how it looks in DESIGN MODE! It’s not pretty, but making it pretty is relatively easy now because the changes I make to the xaml are instantly visible in the designer and I can use Blends Template editor without having to continuously run my solution.

(download demo-project here)

Tags: , , ,