はじめに
「MVVMパターンでアプリケーションを実装するのは面倒だ」
そんな時、簡単に利用できるユーティリティや簡単なツールキットの使用を検討してみてはどうでしょうか。今回は、Silverlight 4の開発で利用できるユーティリティやツールキットを解説します。
RelayCommand
ICommandインターフェイスの実装を行っていると、ExecuteメソッドやCanExecuteメソッド以外はほぼ同じような実装を行えば良いことに気づきます。MVVMを採用した多くのプロジェクトでは、ExecuteメソッドやCanExecuteメソッドをデリゲートで受け取るようにしたRelayCommandというユーティリティクラスを導入して、コマンド実装の手間や修正を簡素化しています。リスト1にRelayCommandのサンプルを示します。
public class RelayCommand<T> : ICommand { private readonly Action<T> _execute; private readonly Func<bool> _canExecute; /// <summary> /// RelayCommandのコンストラクター<br /> /// 引数にExecuteやCanExecuteの実体をデリゲートで受け取る /// </summary> public RelayCommand(Action<T> execute) : this(execute, null) { } public RelayCommand(Action<T> execute, Func<bool> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } public event EventHandler CanExecuteChanged; public void RaiseCanExecuteChanged() { var handler = CanExecuteChanged; if (handler != null) { handler(this, EventArgs.Empty); } } // ExecuteメソッドやCanExecuteメソッドでは受け取ったExecuteやCanExecuteデリゲートを実行するだけ public void Execute(object parameter) { _execute((T)parameter); } public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(); } }
ビューモデル側ではリスト2のように、RelayCommandを利用します。
private RelayCommand<MainPageViewModel> _検索Command; /// <summary> /// 検索コマンドを公開するプロパティです。 /// </summary> public RelayCommand<MainPageViewModel> 検索Command { get { if (_検索Command == null) _検索Command = new RelayCommand<MainPageViewModel>(検索); return _検索Command; } } /// <summary> /// 検索コマンドの本体です。 /// </summary> public void 検索(MainPageViewModel item) { var proxy = new 書籍管理ServiceProxy.書籍管理ServiceClient(); proxy.Find書籍ByIdCompleted += (source, e) => { if (e.Error != null) MessageBox.Show(e.Error.Message); Id = e.Result.Id; タイトル = e.Result.タイトル; 登録日 = e.Result.登録日; ISBN = e.Result.ISBN; TimeStamp = e.Result.TimeStamp; }; int id; if (! int.TryParse(item.SearchId, out id)) return; proxy.Find書籍ByIdAsync(id); }
前回の連載のリスト3で示したコードのExecuteメソッドをビューモデル側の検索メソッドに移動し、RelayCommandをインスタンス化するタイミングでRelayCommandにデリゲートとして引き渡しています。