Livet で Messenger を使ってみる(その参)
本日はさらに踏み込んで、Livet が提供するメッセージングアクションのうち
- InformationDialogInteractionMessageAction
- ConfirmationDialogInteractionMessageAction
- OpenFileDialogInteractionMessageAction
- SaveFileDialogInteractionMessageAction
の四つを試してみたいと思います。これらのアクションを使えば、コードを一切書かずに確認ダイアログやファイル選択ダイアログを使うことも可能になります。
え? ViewModel のコマンドでダイアログ使えばいいじゃんって? 確かにそうなんですが、View にこれらのダイアログを表示する責任を押し付ける*1ことで、ViewModel の単体テストが可能になるというメリットがあります。
ソースのコメントを見ると、各アクションは以下の機能が提供されてます。
InformationDialogInteractionMessageAction | 情報ダイアログを表示するアクションです。 |
ConfirmationDialogInteractionMessageAction | 確認ダイアログを表示するアクションです。 |
OpenFileDialogInteractionMessageAction | 「ファイルを開く」ダイアログを表示するアクションです。 |
SaveFileDialogInteractionMessageAction | 「ファイルを保存する」ダイアログを表示するアクションです。 |
では早速ためしてみましょう。
ViewModel を編集する
Visual Studio 2010 を起動し、新しいプロジェクトを作成します。今回も Visual Basic を選択し*2、Livet WPF4 MVVM アプリケーションを選択。プロジェクト名を「MessagingSample」にして「OK」ボタンをクリックします。
プロジェクトが作成されたらいったんビルドしときましょう。
次に ViewModel にコマンドを作成します。「MainWindowViewModel.vb」を開き、ViewModel にコマンドを四つ追加します。InformCommand は CanExecute 無しの ViewModelCommand を作成するためスニペットを lvcomn と打ち込んでタブキー。それ以外はすべて View からのレスポンスを検知する リスナーコマンド を作るので llcomn のスニペットでコマンドを作ります。
以下の表を参考に展開したスニペットを編集してください。Confirm 〜 Save の三つのコマンドはリスナーコマンドなので、View からのメッセージを受信するため型パラメータを指定します。
スニペット | プレフィックス | コマンドの型パラメータ |
lvcomn | Inform | なし |
llcomn | Confirm | ConfirmationMessage |
llcomn | Open | OpeningFileSelectionMessage |
llcomn | Save | SavingFileSelectionMessage |
するとこうなります。
Public Class MainWindowViewModel Inherits ViewModel #Region "InformCommand" Private _InformCommand As ViewModelCommand Public ReadOnly Property InformCommand() As ViewModelCommand Get If _InformCommand Is Nothing Then _InformCommand = New ViewModelCommand(AddressOf Inform) End If Return _InformCommand End Get End Property Private Sub Inform() End Sub #End Region #Region "ConfirmCommand" Private _ConfirmCommand As ListenerCommand(Of ConfirmationMessage) Public ReadOnly Property ConfirmCommand() As ListenerCommand(Of ConfirmationMessage) Get If _ConfirmCommand Is Nothing Then _ConfirmCommand = New ListenerCommand(Of ConfirmationMessage)(AddressOf Confirm) End If Return _ConfirmCommand End Get End Property Private Sub Confirm(ByVal parameter As ConfirmationMessage) End Sub #End Region #Region "OpenCommand" Private _OpenCommand As ListenerCommand(Of OpeningFileSelectionMessage) Public ReadOnly Property OpenCommand() As ListenerCommand(Of OpeningFileSelectionMessage) Get If _OpenCommand Is Nothing Then _OpenCommand = New ListenerCommand(Of OpeningFileSelectionMessage)(AddressOf Open) End If Return _OpenCommand End Get End Property Private Sub Open(ByVal parameter As OpeningFileSelectionMessage) End Sub #End Region #Region "SaveCommand" Private _SaveCommand As ListenerCommand(Of SavingFileSelectionMessage) Public ReadOnly Property SaveCommand() As ListenerCommand(Of SavingFileSelectionMessage) Get If _SaveCommand Is Nothing Then _SaveCommand = New ListenerCommand(Of SavingFileSelectionMessage)(AddressOf Save) End If Return _SaveCommand End Get End Property Private Sub Save(ByVal parameter As SavingFileSelectionMessage) End Sub #End Region End Class
情報コマンド
InformCommand はとりあえずメッセージを表示するだけにしておきます。
#Region "InformCommand" Private _InformCommand As ViewModelCommand Public ReadOnly Property InformCommand() As ViewModelCommand Get If _InformCommand Is Nothing Then _InformCommand = New ViewModelCommand(AddressOf Inform) End If Return _InformCommand End Get End Property Private Sub Inform() MessageBox.Show("InformCommand コマンドが実行されました。") End Sub #End Region
確認コマンド
ConfirmCommand は少し複雑です。View で表示した確認ダイアログで Yes が押されたのを検知するため、ConfirmationMessage.Responce プロパティで戻り値を判定します。HasValue と Value が True なら Yes が選択されているので、処理を実行します。
#Region "ConfirmCommand" Private _ConfirmCommand As ListenerCommand(Of ConfirmationMessage) Public ReadOnly Property ConfirmCommand() As ListenerCommand(Of ConfirmationMessage) Get If _ConfirmCommand Is Nothing Then _ConfirmCommand = New ListenerCommand(Of ConfirmationMessage)(AddressOf Confirm) End If Return _ConfirmCommand End Get End Property Private Sub Confirm(ByVal parameter As ConfirmationMessage) If (parameter.Response.HasValue AndAlso parameter.Response.Value) Then MessageBox.Show("「はい」が選択されました。") End If End Sub #End Region
開くと保存コマンド
OpenCommand と SaveCommand は 各Message の Response プロパティに選択されたファイル名が入ってきます。このコマンドでは、ファイルが選択されない場合、戻り値は Null (VB なら Nothing) なのでガード節を設けて直ちに抜け、ファイルが選択されたら MessageBox でファイル名を表示するよう実装します。
#Region "OpenCommand" Private _OpenCommand As ListenerCommand(Of OpeningFileSelectionMessage) Public ReadOnly Property OpenCommand() As ListenerCommand(Of OpeningFileSelectionMessage) Get If _OpenCommand Is Nothing Then _OpenCommand = New ListenerCommand(Of OpeningFileSelectionMessage)(AddressOf Open) End If Return _OpenCommand End Get End Property Private Sub Open(ByVal parameter As OpeningFileSelectionMessage) If String.IsNullOrEmpty(parameter.Response) Then Return MessageBox.Show("選択されたファイルは " + parameter.Response + " です。") End Sub #End Region #Region "SaveCommand" Private _SaveCommand As ListenerCommand(Of SavingFileSelectionMessage) Public ReadOnly Property SaveCommand() As ListenerCommand(Of SavingFileSelectionMessage) Get If _SaveCommand Is Nothing Then _SaveCommand = New ListenerCommand(Of SavingFileSelectionMessage)(AddressOf Save) End If Return _SaveCommand End Get End Property Private Sub Save(ByVal parameter As SavingFileSelectionMessage) If String.IsNullOrEmpty(parameter.Response) Then Return MessageBox.Show("保存しようとしたファイル名は " + parameter.Response + " です。") End Sub #End Region
ここまでできたら、次は Blend で作業します。プロジェクトをビルドして保存し、Blend で開いてください。
View をデザインする
View を Blend で開き、画面サイズを「高さ 300・幅 200」に変更します。次に「オブジェクトとタイムライン」で「Grid」を選択、「レイアウトの種類の変更」から「StackPanel」を選択してください。
「アセット」から「Button」を4つ「StackPanel」にドラッグして追加し、以下の順に上から Content を変更します。
- 表示
- 確認
- 開く
- 保存
するとこうなります。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:local="clr-namespace:MessagingSample" x:Class="MainWindow" Title="MainWindow" Height="300" Width="200"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <StackPanel> <Button Content="表示"/> <Button Content="確認"/> <Button Content="開く"/> <Button Content="保存"/> </StackPanel> </Window>
情報表示メッセージ
まず情報表示メッセージから設定しましょう。「アセット」→「ビヘイビアー」→「Livet」→「メッセージング」と展開し、「InformationDialogInteractionMessageAction」を選択。
「オブジェクトとタイムライン」の一番上の Button にドラッグ&ドロップします。
「InformationDialogInteractionMessageAction」のプロパティを編集します。「プロパティ」→「その他」→「DirectInteractionMessage」の「新規作成」をクリックして、「CollbackCommand」の「詳細オプション」→「データバインド」に ViewModel で定義した 「InformCommand」コマンドをバインドします。さらに「Message」の「新規作成」をクリック。図のように
Caption | 表示 |
Image | Asterisk |
Text | 情報を表示します。 |
こんな感じでプロパティを設定します。
ここまで設定したら、F5キーで実行してみましょう。「表示」ボタンをクリックすると、最初に Blend で設定したメッセージが表示されます。
OK ボタンをクリックすると、CollbackCommand でバインドしたコマンドが実行されます。このサンプルではあえてコマンドをバインドさせてますが、ダイアログだけ表示したい場合はコマンドをバインドさせる必要ありませんね。
ここまでの XAML です。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:local="clr-namespace:MessagingSample" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="MainWindow" Title="MainWindow" Height="300" Width="200"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <StackPanel> <Button Content="表示"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:InformationDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding InformCommand, Mode=OneWay}"> <l:InformationMessage Caption="表示" Image="Asterisk" Text="情報を表示します。"/> </l:DirectInteractionMessage> </l:InformationDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> <Button Content="確認"/> <Button Content="開く"/> <Button Content="保存"/> </StackPanel> </Window>
確認メッセージ
次は確認メッセージを設定します。「アセット」→「ビヘイビアー」→「Livet」→「メッセージング」と展開し「ConfirmationDialogInteractionMessageAction」を選択したら、「オブジェクトとタイムライン」で上から二番目の「確認」ボタンにドラッグしてください。
次は「ConfirmationDialogInteractionMessageAction」の設定です。先ほどの確認メッセージと同じようにプロパティを編集します。「プロパティ」→「その他」→「DirectInteractionMessage」の「新規作成」をクリックして、「CollbackCommand」の「詳細オプション」→「データバインド」に ViewModel で定義した 「ConfirmCommand」コマンドをバインドします。さらに「Message」を展開して、以下の図のように各プロパティを設定します。
設定できたら F5キーで実行して動作を確認してみましょう。「確認」ボタンをクリックすると、Message のプロパティで設定したとおり確認ダイアログが表示されます。
「いいえ」をクリックすると何も起きませんが、「はい」を選択すると CollbacckCommand でバインドさせた ConfirmCommand 内の条件が満たされ、ダイアログが表示されます。Visual Studio で Confirm メソッドに渡された ConfirmationMessage.Responce の戻り値をウォッチすれば、より動作が詳しく判ると思います。
ここまでの XAML です。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:local="clr-namespace:MessagingSample" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="MainWindow" Title="MainWindow" Height="300" Width="200"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <StackPanel> <Button Content="表示"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:InformationDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding InformCommand, Mode=OneWay}"> <l:InformationMessage Caption="表示" Image="Asterisk" Text="情報を表示します。"/> </l:DirectInteractionMessage> </l:InformationDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> <Button Content="確認"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:ConfirmationDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding ConfirmCommand, Mode=OneWay}"> <l:ConfirmationMessage Button="YesNo" Caption="確認" Image="Question" Text="実行しますか?"/> </l:DirectInteractionMessage> </l:ConfirmationDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> <Button Content="開く"/> <Button Content="保存"/> </StackPanel> </Window>
開くと保存メッセージ
最後は開くと保存メッセージです。「アセット」から「オブジェクトとタイムライン」の「開く」ボタンに「OpenFileDialogInteractionMessageAction」、「保存」ボタンに「SaveFileDialogInteractionMessageAction」をドロップします。
各メッセージアクションは、以下の画像を参考に設定してください。まず「OpenFileDialogInteractionMessageAction」。「CollbackCommand」は「OpenCommand」とバインドしています。
次は「SaveFileDialogInteractionMessageAction」です。「CollbackCommand」は「SaveCommand」とバインドします。
ここまでできたら F5 で実行します。「開く」ボタンをクリックすると、OpenDialog が起動します。フィルターが指定された拡張子になっていることを確認してください。
キャンセルするとそのまま閉じますが、ファイルを選択して「開く」ボタンをクリックすると、ViewModel で実装したとおりメッセージが表示されます。
完成した XAML です。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:local="clr-namespace:MessagingSample" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="MainWindow" Title="MainWindow" Height="300" Width="200"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <StackPanel> <Button Content="表示"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:InformationDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding InformCommand, Mode=OneWay}"> <l:InformationMessage Caption="表示" Image="Asterisk" Text="情報を表示します。"/> </l:DirectInteractionMessage> </l:InformationDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> <Button Content="確認"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:ConfirmationDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding ConfirmCommand, Mode=OneWay}"> <l:ConfirmationMessage Button="YesNo" Caption="確認" Image="Question" Text="実行しますか?"/> </l:DirectInteractionMessage> </l:ConfirmationDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> <Button Content="開く"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:OpenFileDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding OpenCommand, Mode=OneWay}"> <l:OpeningFileSelectionMessage Filter="テキストファイル(*.txt)|*.txt|すべてのファイル(*.*)|*.*" Title="テキストファイルを開く"/> </l:DirectInteractionMessage> </l:OpenFileDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> <Button Content="保存"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <l:SaveFileDialogInteractionMessageAction> <l:DirectInteractionMessage CallbackCommand="{Binding SaveCommand, Mode=OneWay}"> <l:SavingFileSelectionMessage Filter="テキストファイル(*.txt)|*.txt" Title="テキストを保存"/> </l:DirectInteractionMessage> </l:SaveFileDialogInteractionMessageAction> </i:EventTrigger> </i:Interaction.Triggers> </Button> </StackPanel> </Window>
本日は Livet が提供する4つのメッセージアクションを試してみました。次は機会を見て画面遷移を行うアクション「TransitionInteractionMessageAction」を試してみたいと思います。