d:DataContextでデザイナ用にViewModelを設定する
実行時に引数を伴って生成されるViewModelをデザイナで使用したいことってありませんか?
そういった時はデザイン時属性のd:DataContextを使いましょう。
さくっとやってみる
下記のシナリオでやってみます。
- まず、普通(?)にXAMLでDataContextにViewModelを指定する。
- ViewModelのConstructorで引数を受け取るようにする。
- d:DataContextにサンプルデータを設定する。
まず、普通(?)にXAMLでDataContextにViewModelを指定する。
適当にViewModelを作ってXAMLで指定します。
Public Class HelloWorldViewModel Public Property Display() As String = "Hello, 実行時!" End Class
<UserControl x:Class="SilverlightApplication1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication1.ViewModels" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.DataContext> <local:HelloWorldViewModel/> </UserControl.DataContext> <Grid x:Name="LayoutRoot" Background="White"> <TextBlock Text="{Binding Display}"/> </Grid> </UserControl>
この状態だと、デザイナでも実行時でも「Hello, 実行時!」と表示されます。
ViewModelのConstructorで引数を受け取るようにする。
引数を伴うConstructorを追加します。
Public Sub New(ByVal display As String) Me.Display = display End Sub
すると、例外が発生します。
d:DataContextにサンプルデータを設定する。
これを解決するためにはデザイン用のサンプルデータを作成してd:DataContextに設定します。
まず、XAMLファイルを追加してビルドアクションを「DesignData」にします。次にサンプルデータを編集します。
<local:HelloWorldViewModel xmlns:local="clr-namespace:SilverlightApplication1.ViewModels" Display="Hello, Design!" />
これをd:DataContextで設定して、例外の原因になっている部分はコメントアウトします。
<UserControl x:Class="SilverlightApplication1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication1.ViewModels" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DataContext="{d:DesignData /SampleData/SampleHelloWorld.xaml}" d:DesignHeight="300" d:DesignWidth="400"> <!--<UserControl.DataContext> <local:HelloWorldViewModel/> </UserControl.DataContext>--> <Grid x:Name="LayoutRoot" Background="White"> <TextBlock Text="{Binding Display}"/> </Grid> </UserControl>
これでデザイナを開いてみると……
バッチリ!Constructorのシグネチャに関わらず表示されています。
(ちなみに、デザイン時属性はコンパイル時に無視されるので、このまま実行しても何も表示されません。)
あとは、処理の中で実行時に設定されるように実装します。
Partial Public Class MainPage Inherits UserControl Public Sub New() InitializeComponent() Me.DataContext = New ViewModels.HelloWorldViewModel("Hello, Constructor with Parameter!") End Sub End Class
まとめ
デザイン時属性を使ってデザインをしよう!デザイン時属性はコンパイル時に無視されるので安心!
今回のことは「引数を伴うConstructorだけを持つViewModelをデザイナで使うにはどうしたらいいんだろう」とつぶやいていたところ、@Posaune さんが教えてくださいました。
ありがとうございます。