MVVM模式的3种command总结[2]--RelayCommand
RelayCommand本来是WPF下面用的一种自定义的command,主要是它用到了事件管理函数,这个SL下面是没有的。不过这部分代码如果修改一下,也可以在SL下面使用,和WPF下面的实现思路差不多。
先看下RelayCommand的定义,一共有2种。
1 public class RelayCommand<T> : ICommand 2 { 3 public RelayCommand(Action<T> execute) 4 : this(execute, null) 5 { 6 } 7 8 public RelayCommand(Action<T> execute, Predicate<T> canExecute) 9 { 10 if (execute == null) 11 throw new ArgumentNullException("execute"); 12 13 _execute = execute; 14 _canExecute = canExecute; 15 } 16 17 [DebuggerStepThrough] 18 public bool CanExecute(object parameter) 19 { 20 return _canExecute == null ? true : _canExecute((T)parameter); 21 } 22 public event EventHandler CanExecuteChanged 23 { 24 add{} 25 remove{} 26 //add 27 //{ 28 // if (_canExecute != null) 29 // CommandManager.RequerySuggested += value; 30 //} 31 //remove 32 //{ 33 // if (_canExecute != null) 34 // CommandManager.RequerySuggested -= value; 35 //} 36 } 37 38 public void Execute(object parameter) 39 { 40 _execute((T)parameter); 41 } 42 43 readonly Action<T> _execute = null; 44 readonly Predicate<T> _canExecute = null; 45 46 bool ICommand.CanExecute(object parameter) 47 { 48 throw new NotImplementedException(); 49 } 50 51 event EventHandler ICommand.CanExecuteChanged 52 { 53 add { throw new NotImplementedException(); } 54 remove { throw new NotImplementedException(); } 55 } 56 57 void ICommand.Execute(object parameter) 58 { 59 throw new NotImplementedException(); 60 } 61 }
第一种是采用泛型的Relaycommand定义,这个泛型到底用在哪里还暂时没看明白。
1 public class RelayCommand : ICommand 2 { 3 public RelayCommand(Action execute) 4 : this(execute, null) 5 { 6 } 7 8 public RelayCommand(Action execute, Func<bool> canExecute) 9 { 10 if (execute == null) 11 throw new ArgumentNullException("execute"); 12 13 _execute = execute; 14 _canExecute = canExecute; 15 } 16 17 [DebuggerStepThrough] 18 public bool CanExecute(object parameter) 19 { 20 return _canExecute == null ? true : _canExecute(); 21 } 22 public event EventHandler CanExecuteChanged 23 { //这里把实现注释掉了,这样在SL下面也可以用。 24 add { } 25 remove { } 26 //add 27 //{ 28 // if (_canExecute != null) 29 // CommandManager.RequerySuggested += value; 30 //} 31 //remove 32 //{ 33 // if (_canExecute != null) 34 // CommandManager.RequerySuggested -= value; 35 //} 36 } 37 38 public void Execute(object parameter) 39 { 40 _execute(); 41 } 42 43 readonly Action _execute; 44 readonly Func<bool> _canExecute; 45 }
第二种就是最常用的定义,可以看到在CanExecuteChanged事件里面把commmandmanager方法给注释掉了,就可以在SL下面使用这个类,而且现在看好像也没有什么问题。
在代码上看,Relaycommand和delegatcommand基本上没有啥区别,也是实现了func和action两个参数的办法,基本思路一样。
它们最大的区别就是在前端的调用方式上。delegatecommand使用了expression的SDK里面的interaction来绑定事件,而这种就是直接通过buttonbase的command属性来绑定,因此只能执行单击事件,所以使用范围比较局限,不过如果用interaction来绑定事件的话,其实实现就和delegatecommand一样了。不过为了总结下学习,还是分开来区别下。
前端XAML的代码
<Button x:Name="BTN_CM2" Content="Command2" Height="103" HorizontalAlignment="Left" Margin="115,123,0,0" VerticalAlignment="Top" Width="109" Command="{Binding command2}" />
后台
private ICommand _command2; public ICommand command2 { get { if (this._command2 == null) { this._command2 = new RelayCommand( () => this.cm2Click(), () => this.Cancm2Click); } return this._command2; } set { } } public bool Cancm2Click { get { return true; } } public void cm2Click() { MessageBox.Show("CM2 Clicked!"); }
是不是和delegatecommand很类似?其实就差不多一样的,基本上就是变个类名而已。不过2个类看到的地方不一样,而且前端绑定的方法不同,所以就还是写一下。下一篇就看看解决思路完全不同的attachbehavior模式。