【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 Members public 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 command1 public 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的更多相关文章
- MVVM模式的3种command总结[2]--RelayCommand
MVVM模式的3种command总结[2]--RelayCommand RelayCommand本来是WPF下面用的一种自定义的command,主要是它用到了事件管理函数,这个SL下面是没有的.不过这 ...
- MVVM模式的3种command总结[1]--DelegateCommand
MVVM模式的3种command总结[1]--DelegateCommand 查了不少资料,大概理清楚的就是有3种.当然类名可以自己取了,不过为了便于记忆和区分,还是和看到的文章里面用一样的类名. 1 ...
- 【转】【WPF】MVVM模式的3种command
1.DelegateCommand 2.RelayCommand 3.AttachbehaviorCommand 因为MVVM模式适合于WPF和SL,所以这3种模式中也有一些小差异,比如RelayCo ...
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- WPF MVVM模式的一些理解
/*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...
- WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...
- wpf mvvm模式下CommandParameter传递多参
原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...
- WPF自学入门(十一)WPF MVVM模式Command命令
在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...
- WPF MVVM模式下的无阻塞刷新探讨
很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态.例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度 ...
随机推荐
- git入门基础
git基础 参考: 官网git基础 git 文件的生命周期 文件的生命周期图: git中的文件可以分为4个阶段. Untracked : 这是目录中没有被跟踪的文件,即不在git项目中,使用 git ...
- Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作
1. 在Android的Java层实现文件的读写操作是非常简单的,可以参看之前写的博文:http://blog.csdn.net/conowen/article/details/7296121 在JN ...
- FullPage.js全屏滚动插件解说
1.主要功能 1).支持鼠标滚动 2).多个回调函数 3).支持手机.平板触屏事件 4).支持css3动画 5).支持窗口缩放 6).窗口缩放时自动调整 7).可设置滚动宽度.背景颜色.滚动速度.循环 ...
- linux桥接模式下配置静态ip
原文链接:http://blog.csdn.net/qq_37936542/article/details/79494993 一:桥接模式 VMware桥接模式,也就是将虚拟机的虚拟网络适配器与主机的 ...
- 排序算法 基于Javascript
写在前面 个人感觉:javascript对类似排序查找这样的功能已经有了很好的封装,以致于当我们想对数组排序的时候只需要调用arr.sort()方法,而查找数组元素也只需要调用indexOf()方法或 ...
- bootsrap+jquery+组件项目引入文件的常见报错
做一个项目的时候 ,控制台总是会出现各种bug,其实不用慌张,终结起来也就几种类型的错误,在开发中每次遇到错误都善于总结,下次在看到就会胸有成竹知道是什么情况了,以下是在开发过程中总结的一些错误以及错 ...
- 【基础练习】【线性DP】codevs1576 最长严格上升子序列题解
连题目都不放了,就是标题中说的那样.裸题 于是直接上代码 暑假要来了 好好学习 --炉火照天地,红星乱紫烟. 赧郎明月夜.歌曲动寒川.
- 【p093】细胞分裂
Time Limit: 1 second Memory Limit: 128 MB [问题描述] Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家.现在,他正在为一个细胞实验做准备工作 ...
- 自定义view布局过程详解
布局过程,就是程序在运行时利用布局文件的代码来计算出实际尺寸的过程. 布局分为两个阶段:测量阶段和布局阶段. 测量阶段:从上到下递归地调用每个 View 或者 ViewGroup 的 measure( ...
- 【noip模拟】Fancy Signal Translate (暴力 + 哈希)
题目描述 FST是一名可怜的 OIer,他很强,但是经常 fst,所以 rating 一直低迷. 但是重点在于,他真的很强!他发明了一种奇特的加密方式,这种加密方式只有OIer才能破解. 这种加密方式 ...