The Curious Case of the DesignData msbuild target
Thanks to Karl Shifflet and Unni Ravindranathan, I’ve finally gotten my head around a superior method of populating Blend (and VS 2010’s WPF designer) with sample data. This method, which I am going to call the “DesignData build target”, has the following advantages:
- Blend will render your control as though it’s running with real data, as you design.
- You won’t have to look up and type magic strings when you’re creating your bindings in Blend, Blend will be able to list the possible properties for you. Intellisensational!
- Once compiled, your output dll will have NO baggage associated with your designery frivolities.
- You don’t have to write lots of dummy / mock / stub code
- You don’t even have to finish writing your viewmodel: however you DO have to write all your properties. This is a Good Thing, because it means your bindings will have the right magic strings in them.
How does it work?
First, you need a xaml file that builds up a sample instance of your viewmodel. Then all you have to do is set your Blend-specific DataContext to read from that file.
How do I tell Blend where to get this design data?
I’ve already blogged about the d:DataContext attribute, letting you set up a DataContext but only inside Blend. Another secret of the “d” xml namespace* is the {d:DesignData Source=someDesignDataFile.xaml} markup extension. So all you need in your UserControl or Window’s xaml is (usually on the first element):
d:DataContext=”{d:DesignData Source=someDesignDataFile.xaml}”
Karl’s blog post explains this in a little more depth.
What should be in this design data xaml file?
Just like you usually declare and populate a Window or UserControl, you can actually declare and populate your own view-models as the root element of a xaml file.
I got myself quite confused when I started working with this, because i didn’t realise that the root element of the xaml file should be a declaration of your viewmodel (I was actually placing my viewmodel within a ResourceDictionary >< ):

Here you can see I’ve defined a new ScrumBoardDesignDataDemo.ViewModel.Board, and started assigning some StageNames to it. I’ve used the clr namespace of my viewmodel classes (”ScrumBoardDesignDataDemo.ViewModel”) as the default xml namespace, instead of using what xaml files usually give you: the WPF control namespace. This just cuts down on the amount of typing required.
Normally, if you’re trying to instantiate a class without a public, parameterless constructor in xaml, you’ll get a compiler error. You also won’t be able to set properties that don’t have public setters. This technique allows Blend to do a bit of magic (reflectively creating a doppelganger of your class) that means you can bend the rules a little. More on that in my next post. Let’s just concentrate on getting some sample data into Blend.
By now, if you go into Blend and you try to set up a binding through the binding dialog (you get this by clicking on the peg next to a property, say ItemsSource, and choosing Binding), you’ll get this helpful dialog:

See how the “Fields” tree is populated? That’s Blend’s version of intellisense, which means you no longer have to rely on knowing what the right property name is and hand-typing it.
Don’t go away! We are only half finished. Blend might be helping you choose property names, but we’re left with two more problems:
- Blend isn’t displaying the sample data on screen.
- This xaml file full of things that were only useful during development is being shipped to our customers inside our DLL.
We can fix this with a simple, but quirky little feature. By setting our design data file’s build action to “DesignData” we will have both of our problems fixed. Blend will realise that it’s ok to try and instantiate the object in the xaml file, and MSBuild will leave that xaml file out of our dll.
Setting DesignData build action for the first time
Normally, if you have a look at the properties of a xaml file in visual studio you’ll see that the Build Action is set to “Page”, or in the case of App.xaml it’s “ApplicationDefinition”. You’d think that it’s just a simple matter of typing the word “DesignData” into that combobox, but if you try this, you’ll get an exception message. Karl’s blog post is about a template he wrote that gets over this problem (by creating the file with all the right properties for you), but I had to figure out how the magic worked. It turns out that it’s relatively easy to work around this, you just have to edit the csproj file manually. I’ll walk you through doing this with visual studio – although you could just as easily use notepad.
Save all your files, right click your WPF project and choose “Unload”. This puts your project into a disabled state where you can’t do anything but hand edit the xml – which is exactly what we want to do.
- Right click the (now greyed out) project file and choose “Edit”.
- Locate the design data xaml file:

- Edit the element to be a “DesignData” element with no children:

- Save your csproj file, right click it and choose “Reload”
Now if you compile your project, you’ll find that all traces of this design data have been erased. Even better, if you go back to blend, you’ll see that your sample data is now present (you may have to rebuild or even reload the project):

So hopefully you’ve got another tool in your toolbox to help you (or your graphic designer) be effective in Blend. This is my favourite method so far, however there’s a couple of situations where it might be unsuitable. My next post will be all about why, but just so you know, this doesn’t work well when:
- You want custom logic to occur in your viewmodel at design time (ie a Color property on your viewmodel changes whenever another integer property goes below zero)
- You are using DataTemplates with no Key, just a DataType, and are relying on WPF to find the Template by your ViewModel class. (I understand that Silverlight doesn’t support this anyway, so no problem there!)
As always, I’m keen to know if I got anything wrong. There isn’t much information about the whole “d:” namespace on the internet! Also, my third and final post in this series (about the magic that makes this work and how said magic causes the above problems) will come with a demo project.
* This namespace is actually http://schemas.microsoft.com/expression/blend/2008, but Blend always imports this as “d”