This project has moved. For the latest updates, please go here.

[Info] WPF Design Time Support (Part 1)

Coordinator
Mar 20, 2014 at 6:08 PM
Edited May 14, 2016 at 7:32 PM

This article has been moved to GitHub!


The Visual Studio WPF UI designer and Blend comes with design time support. This helps us to see how the UI will look like during editing the XAML files. Sometimes it is painful to start the application and navigate to a specific view for every single change done in the UI definition. And when we got to the view then we have to ensure that it is filled with some data. Preparing the XAML file to enable design time support with sample data can save us time. Another appreciated feature that comes by using the design time support is IntelliSense for WPF Bindings.

Note: IntelliSense for WPF Bindings requires Visual Studio 2013. Developers who are using the Resharper AddIn get this feature for older Visual Studio versions as well.

The following XAML extract shows how the design time support can be enabled:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:dd="clr-namespace:Waf.Writer.Presentation.DesignData"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="500"
d:DataContext="{d:DesignInstance dd:SampleStartViewModel, IsDesignTimeCreatable=True}"
  • The XML namespace “d” defines the design time extension of the WPF designer. The namespace definition reveals that this feature was originally developed for Blend. Visual Studio supports it fully since the version 2012.
  • The “mc” namespace and the XAML attribute mc:Ignorable="d" is used to guarantee compatibility with the WPF Framework. WPF doesn’t know anything about this design time extension. During runtime all design time attributes will be ignored.
  • The attributes “d:DesignHeight” and “d:DesignWidth” can be used to define the size within the designer. This can be useful, if the size is determined by the content of the element (e.g. Window.SizeToContent).
  • Defining the DataContext at design time can be very useful. The “d:DataContext” attribute allows to specify a class which will be used for IntelliSense when writing a Binding path. The option “IsDesignTimeCreatable=True” tells the designer that it can create the specified class via default constructor. This way it is possible to provide sample data for the UI.
  • I’m using a separate folder “DesignData” within the Presentation layer to define the classes used for design time DataContext. These classes inherit from the original ViewModels. This way we get the correct IntelliSense support. Because the ViewModels require the View and maybe other parameters for the constructor we have to define some MockViews and MockServices. These are just a few lines of code. That’s ok for me because I do not like to adapt the ViewModels just to simplify the design time support.
// Extract from Writer.Presentation/DesignData/SampleStartViewModel

public class SampleStartViewModel : StartViewModel
{
    public SampleStartViewModel() : base(new MockStartView(), new MockFileService())
    {
        ((MockFileService)FileService).RecentFileList = new RecentFileList();
        FileService.RecentFileList.AddFile(
            @"C:\Users\Admin\My Documents\Document 1.rtf");
        FileService.RecentFileList.AddFile(
            @"C:\Users\Admin\My Documents\WPF Application Framework (WAF).rtf");
        FileService.RecentFileList.AddFile(
            @"C:\Users\Admin\My Documents\WAF Writer\Readme.rtf");
        FileService.RecentFileList.RecentFiles.First().IsPinned = true;
    }

    private class MockStartView : MockView, IStartView
    {
    }
}
There is a second way to define the design time DataContext. You can specify a XAML ResourceDictionary via the d:DesignData markup instead of a class. The ResourceDictionary can provide the sample data. However, I prefer the first approach because it is more flexible.