RelayCommand
WPF のための MODEL-VIEW-VIEWMODEL (MVVM) デザイン パターン - MSDN マガジン February 2009
MVVMパターンで使用するコマンドの実装を考えた場合、いろいろなやり方を考えることができると思うが、コマンドの機能毎にICommandの実装を用意する煩雑さとそもそもICommandインタフェースがジェネリクスに対応していないため、本記事のようにデベロッパはAction
RelayCommand.cs (Silverlight4版)
public class RelayCommand: ICommand { readonly Action _execute; readonly Predicate _canExecute; public RelayCommand(Action execute) : this(execute, null) { } public RelayCommand(Action execute, Predicate canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } [DebuggerStepThrough] public bool CanExecute(Object parameter) { return _canExecute == null || _canExecute((T)parameter); } public event EventHandler CanExecuteChanged; public void RaiseCanExecuteChanged() { var handler = CanExecuteChanged; if (handler != null) { handler(this, EventArgs.Empty); } } public void Execute(Object parameter) { _execute((T)parameter); } }
前回書いたNavigateCommandをRelayCommandを拡張して書き直すと、以下のようになる。
NavigateCommand
public class NavigateCommand : RelayCommand{ public NavigateCommand() : base( a => a.NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative)) ) {} }
無理矢理だがXAML構文ではオブジェクト生成時に引数を渡すことも、プロパティでデリゲート構文を差込むこともできないので、このようにデフォルトコンストラクタにラムダでActionデリゲートを挿入している。本来コマンドを単独で使うことはなく、この後言及するであろうViewModelにカプセル化して使うのが普通だ。
XAMLの記述は変わらないので省略する。