WPF: DataTemplates and Design-Time data
2014-08-27 23:42:51 Moscow time
It seems to be useful to have a possibility to edit DataTemplate
rendered with Design-Time data.
First, let's consider the following ViewModel
interface:
internal interface IBookViewModel
{
string Author { get; set; }
string Title { get; set; }
}
Let's also create a separate XAML-file for ResourceDictionary
where the DataTemplate
will be located:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:App.ViewModel"
mc:Ignorable="d">
<DataTemplate DataType="{x:Type viewModel:IBookViewModel}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ResourceDictionary>
Second, let's edit the DataTemplate
using Blend for Visual Studio 2012 (see Expression Studio 4.0: Create or modify a template):
- Open the solution in Blend.
- Locate the XAML-file containing the ResourceDictionary using the "Resources" panel.
- Locate the
DataTemplate
in the list of resources by its Key. - Click "Edit Resource" button.
Blend will show the message "BookViewModelTemplate.xaml cannot be edited in the Design view."
Third, to display Design-Time data attribute d:DataContext
must be used to provide the Design-Time data for the designer.
Also, there is d:DesignInstance
markup extension to simplify the Design-Time instance creation.
Blend uses the following Design-Time-related XAML-namespaces (see DesignData MVVM support in Blend, VS2010 and WPF/Silverlight):
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
To provide the Design-Time Data instance, let's create a class that will implement the ViewModel
interface and contain the appropriate data:
internal sealed class DesignBookViewModel : IBookViewModel
{
public DesignBookViewModel()
{
Title = "Test title";
Author = "Test author";
}
public string Author { get; set; }
public string Title { get; set; }
}
Finally, after experiments it seems the d:DataContext
attributes does not work for DataTemplate
element directly, but the immediate child element of the DataTemplate
.
The following result examples are identical. Both work just fine.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:App.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<DataTemplate DataType="{x:Type viewModel:IBookViewModel}">
<StackPanel Orientation="Vertical"
d:DataContext="{d:DesignInstance Type=viewModel:DesignBookViewModel, IsDesignTimeCreatable=True}">
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ResourceDictionary>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:BlendabilityDataTemplate.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<viewModel:DesignBookViewModel x:Key="DesignBookViewModel" />
<DataTemplate DataType="{x:Type viewModel:IBookViewModel}">
<StackPanel Orientation="Vertical"
d:DataContext="{Binding Source={StaticResource DesignBookViewModel}}">
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ResourceDictionary>
P.S. There is also another approach (out of the scope of this post) – create a DataSource using Blend. It implies adding additional XAML-file that defines ViewModel
instance (i.e. initialization).
The disadvantage of this approach: the ViewModel
can be just an interface or concrete class, but without public setters – no way to set property values using XAML.
More details here:
- DesignData MVVM support in Blend, VS2010 and WPF/Silverlight.
- Blendability Part I – Design time ViewModel.
References:
- Mastering XAML (Design-Time attributes) by Adam Nathan.
- WPF 4.5 Unleashed, Adam Nathan.
StackOverflow references: