How to use the DesignerProperties.GetIsInDesignMode method to populate controls with design time data in WPF using Expression Blend

In this post I’ll be showing how you can use the DesignerProperties.GetIsInDesignMode method to populate controls when you’re designing WPF applications in Expression Blend.

This solution does not work in Visual Studio 2010. To find out about what options do work in Visual Studio check out the following posts:

If you’re looking for a Silverlight solution using DesignerProperties check out the post ‘How to use the DesignerProperties.IsInDesignTool property to populate controls with design time data in Silverlight

The image below shows a user control in Expression Blend which allows users take part in a poll to find out what their favorite colors of the rainbow are.

Expression Blend Without Design Time Data

As you can see it’s difficult if not impossible to imagine what we are actually designing here.

Creating a ViewModelProvider a.k.a ViewModel ServiceLocator

Essentially what we want is to use a ViewModel populated with sample data during design time and the actual ViewModel when the application is running.

To do this we can use the ViewModel and DesignTimeViewModel classes shown below.

public class ViewModel : INotifyPropertyChanged
{
    private string _name;

    public event PropertyChangedEventHandler PropertyChanged;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }

    public ObservableCollection<RainbowColor> RainbowColors { get; set; }

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this,
                new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class DesignTimeViewModel : ViewModel
{
    public DesignTimeViewModel()
    {
        Name = "Roy G Biv";
        RainbowColors = new ObservableCollection<RainbowColor>()
                        {                                    
                            new RainbowColor() {Description = "Red", Color =  "#FFFF0000"},
                            new RainbowColor() {Description = "Orange", Color =  "#FFFFA500"},
                            new RainbowColor() {Description = "Yellow", Color =  "#FFFFFF00"},
                            new RainbowColor() {Description = "Green", Color =  "#FF008000"},
                            new RainbowColor() {Description = "Blue", Color =  "#FF0000FF"},
                            new RainbowColor() {Description = "Indigo", Color =  "#FF4B0082"},
                            new RainbowColor() {Description = "Violet", Color =  "#FFEE82EE"}                                    
                        };
    }
}

public class RainbowColor
{
    public string Description { get; set; }
    public string Color { get; set; }
}

A provider/service locater class allows Expression Blend to determine which ViewModel to use.

public class ViewModelProvider
{
    public ViewModel ViewModel
    {
        get
        {                
            if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
            {
                return new DesignTimeViewModel();
            }
            return new ViewModel();
        }
    }
}

Setting the DataContext to use the ViewModelProvider in XAML

In order to bind the sample data to the user control during design time we need to add a line in the opening tag, create a resource and set the data context to use the ViewModel returned by the provider/service locator.

The lines to do this are highlighted in the XAML for the user control below.

<Window
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="RainbowWpfApplication.MainWindow"
	x:Name="Window"
	Title="MainWindow"
	xmlns:local="clr-namespace:RainbowWpfApplication" 
	Width="600">
	<Window.Resources>
		<DataTemplate x:Key="RainbowTemplate">
			<Border Background="{Binding Color}">
				<StackPanel Margin="10" Orientation="Horizontal">
					<CheckBox/>
					<TextBlock Text="{Binding Description}" 
							   Foreground="Black" 
							   FontWeight="Bold" />
				</StackPanel>
			</Border>
		</DataTemplate>
		<Style x:Key="ListBoxStretchStyle" TargetType="ListBoxItem">
			<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
		</Style>
		<local:ViewModelProvider x:Key="ViewModelProvider" />
	</Window.Resources>
	<Window.DataContext>
		<Binding Source="{StaticResource ViewModelProvider}" Path="ViewModel"/>
	</Window.DataContext>
	<Grid x:Name="LayoutRoot" Background="White">
		<StackPanel Margin="0,0,0,145">
			<TextBlock Text="Choose your favorite colors!" 
					   Margin="5" 
					   TextAlignment="Center" 
					   FontWeight="Bold" />
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition Width="Auto"/>
					<ColumnDefinition Width="*"/>
					<ColumnDefinition Width="Auto"/>
				</Grid.ColumnDefinitions>
				<TextBlock Text="Name:" Margin="10" VerticalAlignment="Center" />
				<TextBox Text="{Binding Name}"  Grid.Column="1"  VerticalAlignment="Center"/>
				<Button Content="Submit" Grid.Column="2" Margin="10"  Width="100" Height="50"/>
			</Grid>
			<ListBox ItemsSource="{Binding RainbowColors}" 
					 ItemContainerStyle="{StaticResource ListBoxStretchStyle}" 
					 ItemTemplate="{StaticResource RainbowTemplate}"/>
		</StackPanel>
	</Grid>
</Window>

The Expression Blend designer will now look like this

Expression Blend With Design Time Data

Does it matter if I’m using MVVM or not?

No. Even though I’m using a ViewModel in this example, all that matters is that you can bind your sample data to the data context of the control.

Comments