原文:【WPF】MVVM模式的3种command

1.DelegateCommand

2.RelayCommand

3.AttachbehaviorCommand

因为MVVM模式适合于WPF和SL,所以这3种模式中也有一些小差异,比如RelayCommand下面的CommandManager方法就是WPF下面的,SL下面无法使用,不过我认为这3种方法中的基本思路都如出一辙,都是出自那位外国牛人的文章里面。主要的区别在于和VIEW中的控件的绑定使用上。有点不同的attachbehaviorcommand是prism4里面的一种设计模式,这个区别有点大。但我自己觉得最方便的还是这个DelegateCommand。

DelegateCommand

    /// <summary>/// Delegatecommand,这种WPF.SL都可以用,VIEW里面直接使用INTERACTION的trigger激发。比较靠谱,适合不同的UIElement控件/// </summary>public class DelegateCommand : ICommand{Func<object, bool> canExecute;Action<object> executeAction;bool canExecuteCache;public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute){this.executeAction = executeAction;this.canExecute = canExecute;}#region ICommand Memberspublic bool CanExecute(object parameter){bool temp = canExecute(parameter);if (canExecuteCache != temp){canExecuteCache = temp;if (CanExecuteChanged != null){CanExecuteChanged(this, new EventArgs());}}return canExecuteCache;}public event EventHandler CanExecuteChanged;public void Execute(object parameter){executeAction(parameter);}#endregion}

这个类大概可以这样来理解,构造函数中的action和func,action负责判断是否执行这个command,action就是触发这个command之后要执行的方法。这样理解最浅显,但对刚熟悉command的我来讲,这样最方便记忆和学习,为了使用ICommand接口实现的方法和事件的解释搜搜就可以找到,但是刚开始理解起来还是有点晦涩。

下面是VM里面用这个command的例子。绑定了一个button控件,最简单例子。cm1Click就是构造函数里面的fuc,负责执行响应事件的方法。Cancm1Click就是构造函数里面的action,负责判断这个Command的响应事件是否执行,这里没有用到判断式,直接赋了一个true.

public class TestViewModels:INotifyPropertyChanged
{public TestViewModels(){......cm1click = new DelegateCommand(cm1Click,Cancm1Click);   //初始化delegatecommand}....//DelegateCommand#region command1public ICommand cm1click { get; set; }public void cm1Click(object param){MessageBox.Show("CM1 clicked!");}private bool Cancm1Click(object param){return true;}#endregion command1......
}

在XAML里面,用interaction来绑定这个事件,而不是在button里面用command来绑定,这样做有个好处,就是非常直观,并且可以响应其他的很多事件

<Button x:Name="BTN_CM1" Content="DelegateCommand" Height="115" Width="148" ><i:Interaction.Triggers><i:EventTrigger EventName="Click"><i:InvokeCommandAction Command="{Binding cm1click}"/></i:EventTrigger></i:Interaction.Triggers></Button>

RelayCommand

RelayCommand本来是WPF下面用的一种自定义的command,主要是它用到了事件管理函数,这个SL下面是没有的。不过这部分代码如果修改一下,也可以在SL下面使用,和WPF下面的实现思路差不多。

先看下RelayCommand的定义,一共有2种。

public class RelayCommand<T> : ICommand{public RelayCommand(Action<T> execute): this(execute, null){}public RelayCommand(Action<T> execute, Predicate<T> canExecute){if (execute == null)throw new ArgumentNullException("execute");_execute = execute;_canExecute = canExecute;}[DebuggerStepThrough]public bool CanExecute(object parameter){return _canExecute == null ? true : _canExecute((T)parameter);}public event EventHandler CanExecuteChanged{add{}remove{} //add//{//    if (_canExecute != null)//        CommandManager.RequerySuggested += value;//}//remove//{//    if (_canExecute != null)//        CommandManager.RequerySuggested -= value;//}}public void Execute(object parameter){_execute((T)parameter);}readonly Action<T> _execute = null;readonly Predicate<T> _canExecute = null;bool ICommand.CanExecute(object parameter){throw new NotImplementedException();}event EventHandler ICommand.CanExecuteChanged{add { throw new NotImplementedException(); }remove { throw new NotImplementedException(); }}void ICommand.Execute(object parameter){throw new NotImplementedException();}}

第一种是采用泛型的Relaycommand定义

public class RelayCommand : ICommand{public RelayCommand(Action execute): this(execute, null){}public RelayCommand(Action execute, Func<bool> canExecute){if (execute == null)throw new ArgumentNullException("execute");_execute = execute;_canExecute = canExecute;}[DebuggerStepThrough]public bool CanExecute(object parameter){return _canExecute == null ? true : _canExecute();}public event EventHandler CanExecuteChanged{   //这里把实现注释掉了,这样在SL下面也可以用。add { }remove { }//add//{//    if (_canExecute != null)//        CommandManager.RequerySuggested += value;//}//remove//{//    if (_canExecute != null)//        CommandManager.RequerySuggested -= value;//}}public void Execute(object parameter){_execute();}readonly Action _execute;readonly Func<bool> _canExecute;}

第二种就是最常用的定义,可以看到在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!");}

【WPF】MVVM模式的3种command相关推荐

  1. MVVM模式的3种command总结[2]--RelayCommand

    MVVM模式的3种command总结[2]--RelayCommand RelayCommand本来是WPF下面用的一种自定义的command,主要是它用到了事件管理函数,这个SL下面是没有的.不过这 ...

  2. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍...

    WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正 ...

  3. C# WPF MVVM模式Prism框架从零搭建(经典)

    01 - 前言 目前最新的PRISM的版本是8.1.97,本节以6.3.0.0 讲解,可以在Github上获取PRISM的源码. Prism Github地址:https://github.com/P ...

  4. C# WPF MVVM模式Prism框架下事件发布与订阅

    01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Prism提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间通过事 ...

  5. C# WPF MVVM模式Caliburn.Micro框架下事件发布与订阅

    01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Caliburn提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间 ...

  6. 使用WPF+MVVM模式的小案例

    WPF+MVVM模式的小案例案例主要的目录结构 下面一步一步建立整个小程序的目录和相应的代码程序. 1.打开VS, 新建项目WPFDemo.Client.CustType(自己可以写自己的程序名称,这 ...

  7. wpf mvvm模式下CommandParameter传递多参

    wpf mvvm模式下CommandParameter传递多参 原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递 ...

  8. WPF MVVM模式 发送DataGird表格的数据到另一个页面显示

    WPF MVVM模式 发送DataGird表格的数据到另一个页面显示 这里我们是使用Messenger消息机制把这个页面的表格行数据发送到另一个页面显示,效果如下图: 首先在这个表格页面的ViewMo ...

  9. WPF MVVM模式的应用——室内监控可视化

    需求 在物联网应用中,可视化端经常需要将实物信息详细的呈现到用户视野之中.在室内环境中,经常可见的设备空调和灯.本次课题主要以室内环境的温湿度和房间用能情况出发,实现室内温湿度和能耗信息的可视化.为了 ...

最新文章

  1. 面向Agent的系统架构
  2. 百度地图轨迹开发,如何绘制带有箭头的折线
  3. word 公式编号 右侧对齐_word排版实例:如何将文档中的公式与文字对齐
  4. Lync-用户-电话号码-更新
  5. Vue.js中的8种组件间的通信方式;3个组件实例是前6种通信的实例,组件直接复制粘贴即可看到运行结果
  6. Qt for Android 开发大坑
  7. gRPC基础--Protobuf编码格式详解
  8. 利用CSS边框合并属性打造table细边框
  9. [Java] 蓝桥杯ALGO-48 算法训练 关联矩阵
  10. JBoss + EJB3 + MySql : 开发第一个EJB
  11. http-server搭建web服务器
  12. 2018自然语言处理与机器学习论文发表统计
  13. 「代码随想录」本周学习小结!(动态规划系列四)
  14. c语言 时间函数,C/C+时间相关的函数
  15. 公测: 机智云自动生成app代码
  16. AT绑定句柄无效和拒绝访问
  17. 基于51单片机的555定时器测电容proteus仿真
  18. 数据库SQLite之嵌入式Linux实际网关项目使用初步
  19. 《C primer plus》——文件输入/输出
  20. 服装实体店运营需要的所有软件,合集在此!(建议收藏)实体店运营 实体店运营干货 实体店运营全流程所需系统推荐

热门文章

  1. win7安装gtp磁盘_GPT转MBR分区格式安装win7/win10系统教程
  2. php error 2,一起搞懂PHP的错误和异常(二)
  3. 华为云计算之储存基础知识
  4. Linux下的awk用法详解
  5. 数据库系统概论:第六章 关系数据库理论
  6. sap在线服务器,SAP服务器常用端口
  7. c语言线性表的逆转,数据结构(C语言)设有一个线性表E,将线性表逆置,要求逆线性表占? 爱问知识人...
  8. asyncdata连接php,如何使用Nuxt和asyncData观察路由更改
  9. Mysql内置优化工具show profiles
  10. Linux如何查看进程、杀死进程、查看端口等常用命令