コマンドバインディング
コマンドバインディングは、コマンドの実装ロジックをビューモデルのプロパティとして公開することで、コードビハインドからイベントハンドラを排除し、意味的なコマンドをビューから直接指定する仕組みです。WPFにはもともと存在していましたが、Silverlightではバージョン4で新たに追加されました。
Silverlightでコマンドを利用したい場合には、次の手順でコマンドを作成し、ビューにバインドする必要があります。
- ICommandインターフェースを実装したコマンドを作成する
- ViewModelのプロパティとしてコマンドを公開する
- ICommandSourceインターフェースを実装したクラスにバインドする
1つずつ見ていきましょう。
1. ICommandインターフェースを実装したコマンドを作成する
コマンドバインディングするコマンドは、ICommandインターフェースを実装している必要があります。例えば検索を行うコマンドを実装する場合には、次の表のメソッドやプロパティを実装する必要があります。
| No | 実装する項目 | 説明 |
| 1 | CanExecuteChanged | 実行状態が変更された場合に発生するイベントハンドラ |
| 2 | CanExecute | 検索を行っていいか判断するメソッド |
| 3 | Execute | コマンドの実体を記述するメソッド |
ICommandを実装したコマンドオブジェクトの実装例をリスト3に示します。
public class Find書籍Command : ICommand
{
public Find書籍Command() { }
/// <summary>
/// 実行状態が変更された場合に発生するイベントハンドラ
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// CanExecuteChangedイベントを発生させ、CanExecuteメソッドを実行します。
/// </summary>
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
/// <summary>
/// コマンドが実行可能か調査するメソッド
/// 例えばボタンにコマンドがバインドされた場合、このメソッドの返却値によってボタンのIsEnableプロパティが変化します。
/// </summary>
public bool CanExecute(object parameter)
{
var item = parameter as MainPageViewModel;
if (item == null)
return true ;
return ! item.HasChange;
}
/// <summary>
/// コマンドの実体を記述するメソッド
/// </summary>
public void Execute(object parameter)
{
var item = (MainPageViewModel)parameter;
// WCFサービスの検索メソッドを呼び出し結果をビューモデルに格納する。
var proxy = new 書籍管理ServiceProxy.書籍管理ServiceClient();
proxy.Find書籍ByIdCompleted += (source, e) =>
{
if (e.Error != null)
MessageBox.Show(e.Error.Message);
item.Id = e.Result.Id;
item.タイトル = e.Result.タイトル;
item.登録日 = e.Result.登録日;
item.ISBN = e.Result.ISBN;
item.TimeStamp = e.Result.TimeStamp;
item.HasChange = false;
};
int id;
if (!int.TryParse(item.SearchId, out id))
return;
proxy.Find書籍ByIdAsync(id);
}
}
画面に表示されたボタンは、状況によって実行されてほしくない場合があります。
例えば、値がロードされていないのに更新ボタンが実行されるのはおかしかったり、更新途中なのに再度検索を実行してほしくないといった場合です。
ICommandインターフェースでは、バインドされたコントロールはCanExecuteメソッドで現在自分は実行してよいのかを確認します。コマンドの実行が可能になったら、プログラム側でCanExecuteChangedイベントを呼び出すことで、コントロールが再度CanExecuteメソッドを通じて状態を確認します。
今回はRaiseCanExecuteChangedメソッドを公開することで、ビューモデル側からCanExecuteChangedイベントを実行できるようにしています。
Executeメソッドは、そのコマンドで実行した処理の実体です。ここでは、引数に与えられたViewModelのIdプロパティをもとに、サーバ側のWCFサービスを呼び出し検索を実行しています。
2. ViewModelのプロパティとしてコマンドを公開する
コマンドを作成したので、ビューモデル側にリスト4のようなプロパティを用意し、コマンドを公開します。
public Find書籍Command _検索Command;
public Find書籍Command 検索Command
{
get {
if (_検索Command == null)
_検索Command = new Find書籍Command();
return _検索Command;
}
}
3. ICommandSourceインターフェースを実装したクラスにバインドする
コマンドをバインディングできるのは、ICommandSourceインターフェースを実装したコントロールだけです。Silverlight 4では、次のコントロールが標準でコマンドバインディングを利用できます。
- Button
- MenuItem
- HyperLink
この他のコントロールや、クリックイベント以外でコマンドバインディングを利用したい場合は、ICommandSourceインターフェースを実装したコントロールを作成するか、後述するビヘイビアを利用します。
ここまでで、書籍検索を行うサンプルが完成しました。
Visual Studioでサンプルを実行してみてください。添付したサンプルには更新や削除といった機能も追加しているので、気になる方はダウンロードしてみてください。
まとめ
前編では、MVVMパターンとは何か、SilverlightでどのようにMVVMパターンを実装すればよいかといった基本的な部分に触れました。次回(後編)では、MVVMパターンをもっと簡単に実装する方法、ツールについて解説していきます。
