最近、「ひと目でわかる Visual C# 2013/2012 アプリケーション開発入門」を参考にアプリを作っています。
ひと目でわかる Visual C# 2013/2012 アプリケーション開発入門 (MSDNプログラミングシリーズ)
ただ、MessageBoxの表示について、より良さそうな方法があったため、メモを残しておきます。
2015/12/10 追記 ここから
公式Blogに以下の記事が掲載されましたので、Microsoft.TeamFoundation.MVVM
の使用前に記事を確認してみてください。
Microsoft.TeamFoundation.MVVM 名前空間の利用について - Visual Studio サポート チーム blog - Site Home - MSDN Blogs
2015/12/10 追記 ここまで
環境
- Windows7
- .NET Framework 4.5
- 作るもの:ボタンを押したらメッセージを表示する
なお、ボタンを押した時のコマンド実行やMessageBoxの表示 (DataContextChangedイベントハンドラー編)の詳細な説明は、上記書籍に説明があるかと思います。
ボタンを押した時のコマンド実行について
今回は、以下のようにしてコマンド実行をButton要素へデータバインドしています(詳細な説明は上記書籍を参照)。
ViewModel
ICommand型のプロパティを用意し、その中でRelayCommand
を使ってコマンド実行のデリゲートを渡し、ExecuteShowCommandメソッドに実際の処理を書きます。
class MessageBoxServiceViewModel : Microsoft.TeamFoundation.MVVM.ViewModelBase { private ICommand _showCommand; public ICommand ShowCommand { get { if (_showCommand == null) { _showCommand = new Microsoft.TeamFoundation.MVVM.RelayCommand(ExecuteShowCommand); } return _showCommand; } } private void ExecuteShowCommand(object x) { // コマンド実行時の処理 } }
View
xamlのButton要素へ、ICommand型のプロパティ(ここではShowCommand)をデータバインドして完成です。
<Button Command="{Binding Path=ShowCommand}"></Button>
MessageBoxの表示 (DataContextChangedイベントハンドラー編)
処理自体はViewModel内のExecuteShowCommandメソッドの中へ書けばいいのですが、Viewと分離するためにいろいろと追加します。
ViewModel
publicなActionデリゲートを用意して、ExecuteShowCommandでActionデリゲートを呼びます。
public Action<string> ShowInformationMessageBox { get; set; } private void ExecuteShowCommand(object x) { ShowInformationMessageBox("hoge"); }
View
コードビハインドで、ViewのMessageBoxとViewModelのActionプロパティを紐付ける、DataContextChangedイベントハンドラーを書きます。
x.ShowInformationMessageBox = (message) => MessageBox.Show(message, "info", MessageBoxButton.OK, MessageBoxImage.Information);
この方法でもいいのですが、画面ごとにMessageBox向けのActionデリゲートとコードビハインドを追加しなくてはならず、少々面倒に感じていました。
MessageBoxの表示 (MessageBoxService編)
他により良い方法がないかと探してみたところ、フォーラムにgekkaさんのコードがありました。
Microsoft.TeamFoundation.MVVMを利用してViewModelからMessageBoxを表示させる方法
ただ、
var mbs = base.ResolveService<Microsoft.TeamFoundation.MVVM.IMessageBoxService>();
mbs.Show(Name);
とResolveService
を使って解決している部分が気になりました。
Microsoft.TeamFoundation.MVVM.ViewModelBase
に使えるものがないかをMSDNを見たところ、MessageBoxService
というgetアクセサのみを持つプロパティがありました。
ViewModelBase.MessageBoxService プロパティ (Microsoft.TeamFoundation.MVVM) - MSDN
そこで、MessageBoxServiceによるMessageBoxの表示を試してみます(ようやく本題)。
ViewModel
MessageBoxServiceプロパティを使うことで、ExecuteShowCommandメソッドは簡潔になります。
private void ExecuteShowCommand(object x) { MessageBoxService.ShowInformation("hoge"); }
なお、MessageBoxServiceはIMessageBoxService型を返すため、エラー表示をするShowError()
メソッドや、MessageBox.Show()と同じような使い方ができるShow()
メソッドも使えたりします。
IMessageBoxService インターフェイス (Microsoft.TeamFoundation.MVVM) - MSDN
View
xamlのWindow要素に以下を追加します。
xmlns:mvvm="clr-namespace:Microsoft.TeamFoundation.MVVM;assembly=Microsoft.TeamFoundation.Controls" mvvm:MVVMSupport.ViewModel="{Binding}"
なお、xamlに追加していない場合は、実行時に以下のエラーが表示されます。
Service not found: Microsoft.TeamFoundation.MVVM.IMessageBoxService. Make sure that 'mvvm:MVVMSupport.ViewModel="{Binding}"' is in your .xaml file.
また、Viewのコードビハインドが不要となるため、以上でDataContextChangedと同じ処理になります。
感想
DataContextChangedイベントハンドラーと比べてMessageBoxServiceでは、
- Viewではメッセージボックスを表示するためのコードビハインドがなくなった
- xamlのWindow要素への追加が増えたものの、ほぼ定型文
- ViewModelではActionプロパティが不要になった
となり、より簡潔に書けそうです。
なお、Microsoft.TeamFoundation.MVVM名前空間に関する情報があまり見つからなかったため、何か不具合があるかもしれません。
その時は都度追加していければと思います。
ソースコード
GitHubに上げました(プロジェクト名は「MessageBoxMVVM」)。
CSharp-Sample/MVVMApp/MessageBoxMVVM at master - thinkAmi/CSharp-Sample - GitHub
なお、GitHub上のコードでは、MessageBoxService.ShowInformation()の他に、ShowError()やShow()なども使っています。