DesignData MVVM support in Blend, VS2010 and WPF/Silverlight

When developing a solution using WPF or Silverlight, there are normally designers working in Blend and developers working with them in Visual Studio 2010. Often it is impractical for designers to use data from live systems (e.g. they don’t want to install SQL etc.) but they need data to flesh out the user interface so that they can style it and edit templates. For example a ListBox with no data is difficult to style in Blend, and certainly impossible to visualise. For this reason there is often a need to provide design time data that mimics the real runtime data.

The first cut approach to this is to put the mock data into XML files and then parse them into Plain-Old CLR Objects (POCOs), but this requires writing and maintaining an XML parser in your application. You’ve probably already realised that the XAML parser is pretty good at creating POCOs from XML – it is what it does for a living – so a far better approach than plain XML files is to create your POCO object graph through XAML and let the Silverlight/WPF XAML parser do the heavy lifting. You can then bind your user interface to this dummy data and get all your databindings correct and working, then switch it out at runtime for the real thing. Indeed this approach has been adopted by the Blend team, and there is UI support for this in Blend (the DATA tab) to allow you to create, edit and maintain the tree of design time data.

However, this situation isn’t ideal as you have a graph of dummy data which is included in your application at runtime but not used (it is only used during design time). Enter the DesignData markup extension and build action.

You’ve probably noticed that Blend adds the following namespace declarations to your XAML files:

 mc:Ignorable="d" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" 

so what’s this all about? Well this is a pretty neat feature that allows Blend to set properties and attributes that are ignored at runtime. You’ve probably seen:

 d:DesignHeight="350" d:DesignWidth="525" 

which hints to Blend what size to draw a control at when viewed in the designer, without affecting runtime layout. Pretty neat! Well the DesignData markup extension takes this a step further.

To use DesignData, first create, as normal, your POCO objects that will hold your data in your view model. You should implement INotifyPropertyChanged so that your bindings update when the data changes. I am going to use the classic Person object as an example:

 using System.Collections.ObjectModel;
using System.ComponentModel; 
 
namespace WpfApplication5
{
    public class Person : INotifyPropertyChanged
    {
        private string personName;
        public string PersonName
        {
            get
            {
                return this.personName;
            } 

            set
            { 

                if (this.personName != value)
                {
                    this.personName = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("PersonName"));
                    }
                }
            }
        } 
 
        private int age;
        public int Age
        {
            get
            {
                return this.age;
            } 

            set
            { 

                if (this.age != value)
                {
                    this.age = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("Age"));
                    }
                }
            }
        } 
 
        private string phoneNumber;
        public string PhoneNumber
        {
            get
            {
                return this.phoneNumber;
            } 

            set
            { 

                if (this.phoneNumber != value)
                {
                    this.phoneNumber = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("PhoneNumber"));
                    }
                }
            }
        } 
 
        public event PropertyChangedEventHandler PropertyChanged;
    } 
 
    public class Persons : ObservableCollection<Person> { } 
 
} 

Next, in order to use DesignData, create a separate standalone XAML file that defines your view model:

 <Persons xmlns="clr-namespace:WpfApplication5"> 
    <Person PersonName="Joe Soap" Age="21" PhoneNumber="0118 909 1234"/> 
    <Person PersonName="Fred Bloggs" Age="35" PhoneNumber="0118 909 4321"/> 
    <Person PersonName="Bill Gates" Age="46" PhoneNumber="0118 909 1111"/> 
    <Person PersonName="Steve Jobs" Age="40" PhoneNumber="0118 909 2222"/> 
</Persons> 

Now set the build action in VS2010 for this file to DesignData:

image_2_5086E807

Now you have a design time object graph! Its as simple as that. This will not be loaded or created at runtime, it is not part of your running application.

In order to use this graph, you can set the d:DataContext anywhere in your application, using the DesignData markup extension and specifying the name of your data file. Note that this only affects the DataContext at design time, not the runtime DataContext. Also note that you need “..\” in your path if you are using Silverlight.

 <Grid> 
    <ItemsControl d:DataContext="{d:DesignData Source=DesignTimeData.xaml}" ItemsSource="{Binding .}"> 
        <ItemsControl.ItemTemplate> 
            <DataTemplate> 
                <StackPanel> 
                    <TextBox Text="{Binding PersonName}"/> 
                    <TextBox Text="{Binding PhoneNumber}"/> 
                </StackPanel> 
            </DataTemplate> 
        </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Grid> 

and that’s it! Your will see data in Blend and the VS2010 designer and you can style to your heart’s content:

image_4_5086E807

Also the data binding dialog in Blend will pick up your properties:

image_6_5086E807 

For completeness, there’s a couple of extra details that you might like to know. Blend and the VS2010 designer actually clone your POCO objects and create new objects that have the same properties as your objects. This is so that the designer doesn’t have to create your objects at design time as they may throw exceptions and interfere with the designer. If you want to suppress this behaviour, you can set your BuildAction to DesignDataWithDesignTimeCreatableTypes:

image_8_5086E807

The designer will now create your real objects.

There is also a d:DesignInstance markup extension. This just defines the type to use without actually creating any data objects. It is useful to light up the data binding dialog in Blend even when you haven’t set up any mock test data. It allows Blend to know the data type of the data context so it can suggest suitable data bindings. It also has a IsDesignTimeCreatable attribute to control cloning.

 <ItemsControl d:DataContext="{d:DesignInstance local:Persons, IsDesignTimeCreatable=True}">

Resources:

Design Data: https://msdn.microsoft.com/en-us/library/ff602279(VS.95).aspx

DesignData msbuild target: https://www.robfe.com/2009/12/the-curious-case-of-the-designdata-msbuild-target/

Design Instance: https://www.codeproject.com/Articles/43335/d-DesignInstance-d-DesignData-in-Visual-Studio-201.aspx

Written by Paul Tallett