Expression Blend触ってて気づいた機能がありました、BehaviorのところにあるCallMethodActionの設定とかドラッグアンドドロップだけで出来るんですね・・・。あとは、ViewModelのDataContextの設定とか、その他もろもろがGUIでサクサクっと出来ちゃう。これはたまりませんな〜。ということで今日見つけた機能です。
ViewとViewModelの関連付け
とりあえずSilverlight(WPFでも可)アプリケーションを作ってPrismを参照に追加に追加して、こんなViewModelをさくっと作成します。特に難しいところはないです。メソッド1つとプロパティ1つあるだけの何の変哲もないクラスです。
namespace MVVMSilverlight.ViewModels { using System; using Microsoft.Practices.Prism.ViewModel; public class MainPageViewModel : NotificationObject { private string message; public string Message { get { return this.message; } set { this.message = value; this.RaisePropertyChanged(() => Message); } } public void Greet() { this.Message = "こんにちは! " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); } } }
ViewとViewModelの関連付け
ここからは、Expression Blendに作業環境をうつします。ViewModelとViewの関連付けからやります。まず、データウィンドウのデータソースの作成からオブジェクトデータソースの作成を選びます。
そして、データソース名とデータソースのクラスを選択してOKを押します。ここではデータソース名をviewModelとして、クラスを先ほど作ったMainPageViewModelにしています。
そうすると、データウィンドウにviewModelという名前で以下のような感じに表示されます。
XAML的には、どうなっているかというとUserControlのResourcesにMainPageViewModelが登録されている感じです。
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:MVVMSilverlight_ViewModels="clr-namespace:MVVMSilverlight.ViewModels" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="MVVMSilverlight.MainPage" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <MVVMSilverlight_ViewModels:MainPageViewModel x:Key="viewModel" d:IsDataSource="True"/> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"/> </UserControl>
そして、これをLayoutRootのGridのDataContextに設定してやります。これはデータウィンドウからGridにドラッグアンドドロップで関連付け出来ます。MainPageViewModelをつまんで画面にぽとっとやるだけです。親切にDataContextに設定してあげるというガイドまで出てきます。
ドロップすると、Gridを選択した状態でデータウィンドウが以下のような表示になります。DataContextが何に割り当てられているのか一目瞭然ですね。
Bindingもドラッグアンドドロップ
次にデータのバインドをやってみます。TextBlockを画面に1つ置きます。そして、TextBlockにMessageプロパティをドラッグアンドドロップします。そうするとバインドしてやるぜ!ってガイドが出てくるのでぽとっと落とします。
XAML的には以下のような感じになります。ちゃんとバインドされてますね。
<TextBlock HorizontalAlignment="Left" Margin="32,24,0,0" TextWrapping="Wrap" Text="{Binding Message}" VerticalAlignment="Top"/>
CallMethodActionもドラッグアンドドロップ
次にボタンを画面に置いてGreetメソッドをボタンにドラッグアンドドロップすると・・・。
トリガーされたらメソッドを呼び出すだと・・・!?以下のようなXAMLが作成されます。
<Button Content="Button" HorizontalAlignment="Left" Margin="53,48,0,0" VerticalAlignment="Top" Width="75"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction MethodName="Greet" TargetObject="{Binding}"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>
なんてこった。今までボタンにアセットからCallMethodActionをドラッグアンドドロップして個別にプロパティを設定してたよorz
もちろんCommandもドラッグアンドドロップ
さっきのはViewModelのメソッドを直接ボタンに割り当ててましたが、以下のようにViewModelにCommandを定義するようにして
namespace MVVMSilverlight.ViewModels { using System; using Microsoft.Practices.Prism.ViewModel; using Microsoft.Practices.Prism.Commands; public class MainPageViewModel : NotificationObject { private string message; private DelegateCommand greetCommand; public string Message { get { return this.message; } set { this.message = value; this.RaisePropertyChanged(() => Message); } } public DelegateCommand GreetCommand { get { return this.greetCommand = this.greetCommand ?? new DelegateCommand(this.Greet); } } private void Greet() { this.Message = "こんにちは! " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); } } }
Blendの画面でGreetCommandをボタンにドラッグアンドドロップすると、素敵にバインドしてくれます。
XAMLは以下のような感じになってました。ばっちりですね。
<Button Content="Button" HorizontalAlignment="Left" Margin="53,48,0,0" VerticalAlignment="Top" Width="75" Command="{Binding GreetCommand, Mode=OneWay}"/>
感想
Visual StudioでXAMLを手書きするのとは大きく違う・・・。やっぱお仕事で高い生産性を求められてる場合にはBlend必須なのかな〜と思った今日この頃でした。