WPFの便利な機能 ApplicationCommands
WPFでは標準的なコマンドを定義を定義したクラスApplicationCommandsがあります。
このクラスには終了を表すプロパティCloseが定義されており、以下のように利用することができます。
MainWindow.xaml
<Window x:Class="WpfApplication01.MainWindow" ...> <Window.CommandBindings> <CommandBinding Command="Close" Executed="CommandBinding_Executed" CanExecute="CommandBinding_CanExecute" /> </Window.CommandBindings> <Grid> <Button Content="おしまい" Command="Close" /> </Grid> </Window>
MainWindow.xaml.cs
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { Close(); // ウィンドウを閉じる } private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; // 無条件で実行可能 }
これだけで十分ですが、MVVMにこだわりたいのでコードビハインドにハンドラを書かずにBehaviorに役割を渡します。
ApplicationCommands.CloseをBehaviorで実現する
先ほどのイベントハンドラで実装した内容をそのままBehaviorで実現します。
ApplicationCommandBehavior.cs
public class ApplicationCommandBehavior : Behavior<Window> { protected override void OnAttached() { base.OnAttached(); CommandBinding CloseCommandBinding = new CommandBinding( ApplicationCommands.Close, CloseCommandExecuted, CloseCommandCanExecute); AssociatedObject.CommandBindings.Add(CloseCommandBinding); } private void CloseCommandExecuted(object target, ExecutedRoutedEventArgs e) { AssociatedObject.Close(); e.Handled = true; } private void CloseCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } }
名前はApplicationCommandBehaviorですがCloseしか書いてません。
このBehaviorをMainWindow.xamlに記述します。
MainWindow.xaml
<Window x:Class="WpfApplication01.MainWindow" ...> <i:Interaction.Behaviors> <local:ApplicationCommandBehavior /> </i:Interaction.Behaviors> <Grid> <Button Content="おしまい" Command="Close" /> </Grid> </Window>
こうするとコードビハインドにイベントハンドラがなくなりすっきりしました。
ViewModelにWindowが閉じることを知らせる
次にWindowが閉じることをViewModelに知らせる方法を実装します。
これは、Closingイベントハンドラにコマンドを割り当てるのが一般的だと思います。
MainWindow.xaml
<Window x:Class="WpfApplication01.MainWindow" ...> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <i:Interaction.Behaviors> <local:ApplicationCommandBehavior /> </i:Interaction.Behaviors> <i:Interaction.Triggers> <i:EventTrigger EventName="Closing"> <i:InvokeCommandAction Command="{Binding Path=ClosingCommand}" /> </i:EventTrigger> </i:Interaction.Triggers> <Grid> <Button Content="おしまい" Command="Close" /> </Grid> </Window>
iとは?
サンプルのソースコードを端折りすぎてますね。
ソース中の”…”ですが、実際はxmlns:~の記述があると思います¥。
xmlns:i=”http://schemas.microsoft.com/expression/2010/interactivity”
と記述することでiを使えるようになります。
併せて参照のDLLが必要になるので申し訳ありませんが、かずきさんのブログ「Visual Studioから使うExpression BlendのBehavior達」を参考にしていただければと思います。