WPF自学入门(十一)WPF MVVM模式Command命令
在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新。但是这并不是我们使用MVVM的正确方式。正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了Xaml文件和CS文件的耦合度,分离界面和业务逻辑,所以我们要尽可能的在View后台不写代码。但是这个例子中,我们将更新ViewModel的代码写在了View里,下一个例子中,我们要通过命令(Command)的来将Button的事件分离出来。
因为本文中需要使用Command命令,我们先来简单了解Command命令。在WPF中使用命令的步骤很简单
1.创建命令
2.绑定命令
3.设置命令源
4.设置命令目标
WPF中命令的核心是System.Windows.Input.ICommand接口,所有命令对象都实现了此接口。当创建自己的命令时,不能直接实现ICommand接口,而是要使用System.Windows.Input.RouteCommand类,该类已经实现了ICommand接口,所有WPF命令都是RouteCommand类的实例。在程序中处理的大部分命令不是RoutedCommand对象,而是RoutedUICommand类的实例,它继承自RouteCommand类。
WPF提供了一个很好的方式来解决事件绑定的问题--ICommand。很多控件都有Command属性,如果没有,我们可以将命令绑定到触发器上。接下来我们来先实现一个ICommand接口。ICommand需要用户定义两个方法bool CanExecute和void Execute。第一个方法可以让我们来判断是否可以执行这个命令,第二个方法就是我们具体的命令。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
/***********************作者:黄昏前黎明后**********************************
* 作者:黄昏前黎明后
* CLR版本:4.0.30319.42000
* 创建时间:2018-04-05 22:57:56
* 命名空间:Example3
* 唯一标识:b9043d4c-fdd7-4e0f-a324-00f0f09286d0
* 机器名称:HLPC
* 联系人邮箱:hl@cn-bi.com
*
* 描述说明:
*
* 修改历史:
*
*
*****************************************************************/
namespace Example3
{
public class RelayCommand : ICommand
{
#region 字段
readonly Func<Boolean> _canExecute;
readonly Action _execute;
#endregion
#region 构造函数
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<Boolean> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand的成员
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
[DebuggerStepThrough]
public Boolean CanExecute(Object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(Object parameter)
{
_execute();
}
#endregion
}
}
我们再在我们的NameViewModel中声明一个ICommand字段:
#region 命令
void UpdateNameExecute()
{
this.UserName = "黄昏前黎明后";
this.CompanyName = "中软易通科技";
}
bool CanUpdateNameExecute()
{
return true;
}
public ICommand UpdateName { get { return new RelayCommand(UpdateNameExecute, CanUpdateNameExecute); } }
#endregion
最后,我们再将事件绑定上这个Command:
<Button Content="更新" Command="{Binding UpdateName}" Margin="20"/>
运行一下,看结果。我们成功将事件分离了出来。

看到上面的结果,似乎目前为止我们已经很好的解决了所有的问题。我们看到运行的数据,事件都是绑定的,实现了界面的完美分离。实际在处理问题是好像需要考虑通用性,这时我们能否把MVVM提取出来作为一个框架,来去更好的解决问题。下一次我们一起来看看怎么进行提取成为通用框架。
本文的DEMO下载地址:WPFMVVMDemo2.zip
WPF自学入门(十一)WPF MVVM模式Command命令的更多相关文章
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- WPF Prism框架下基于MVVM模式的命令、绑定、事件
Prism框架下的自定义路由事件和命令绑定 BaseCode XAML代码: <Button x:Class="IM.UI.CommandEx.PrismCommandEx" ...
- WPF自学入门(十二)WPF MVVM模式提取函数
我们平时在写代码时为了不重复写代码,会进行复制代码或者写通用方法.今天我们就来把上传做的函数提取成为通用的方法调用.把上次写的函数提取为两个主要的文件:ObserableObject和RelayCom ...
- WPF自学入门(六)WPF带标题的内容控件简单介绍
在WPF自学入门(二)WPF-XAML布局控件的文章中分别介绍StackPanel,WarpPanel,DockPanel,Grid,Canvas五种布局容器的使用,可以让我们大致了解容器可以使用在什 ...
- WPF自学入门(三)WPF路由事件之内置路由事件
有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,是否还记得在WPF自学入门(一 ...
- WPF自学入门(十)WPF MVVM简单介绍
前面文章中,我们已经知道,WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 我们不管 ...
- WPF快速入门系列(8)——MVVM快速入门
一.引言 在前面介绍了WPF一些核心的内容,其中包括WPF布局.依赖属性.路由事件.绑定.命令.资源样式和模板.然而,在WPF还衍生出了一种很好的编程框架,即WVVM,在Web端开发有MVC,在WPF ...
- Windows Phone 十一、MVVM模式
MVVM 模式介绍 模型-视图-视图模型 (MVVM) 是一种用来分离 UI 和非 UI 代码的应用设计模式 MVVM – 模型(Model) MVVM 中的 Model 与 MVC 中的一致,用于封 ...
- WPF自学入门(一)WPF-XAML基本知识
一.基本概念 1.XAML是派生自XML的可扩展应用程序标记语言(Extensible Application Markup Language)由微软创造应用在WPF,Silverlight等开发技术 ...
随机推荐
- 微信小程序之换肤的功能
pc或者移动端实现换肤功能还是比较简单的,大致就是需要换肤的css,还有正常的css:把当前皮肤类型存入本地:然后通过js读取并判断当前应该加载哪套css. 由于微信小程序没有操作wxss的api,所 ...
- RBM如何训练?
RBM(Restricted Boltzman Machine,受限玻尔兹曼机)是深度学习的基础,虽然原理比较简单,但实际训练中用到了很多trick,在参考文献中,Hinton为我们披露了几个训练的细 ...
- JAVA面向对象思想
1.面向对象的基本特征 面向对象具有三个基本特征:封装.多态.继承. 1)封装 封装指的是将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能. ...
- Django 2.0 学习(04):Django数据库
数据库设置/配置 打开mysite/settings.py,我们会发现Django是用的是默认的数据库SQLite,如下图所示: Django也是支持其它数据库的,比如PostgreSQL.MySQL ...
- EasyUI动态加载panel,并给panel添加内容
例子: 给布局内动态添加一个panel,给panel一个id,加内容的时候加到这个id里就可以了 var str=$('<div> <textarea id="contex ...
- 在Jenkins中配置执行远程shell命令
1.想要 远程登录到linux服务器并执行相应的shell脚本,需要在jenkins上安装插件enkins SSH plugin 2. 安装了这个插件后,进入系统的配置管理中配置 SSH remote ...
- es6使用技巧
##1.通过参数默认值实现强制参数 ES6 的参数默认值只有在真正使用时才会求值.这可以让你强制确保提供参数: /** * Called if a parameter is missing and * ...
- 排序算法Java实现(直接插入排序)
算法描述:对于给定的一个数组,初始时假设第一个记录自成一个有序序列,其余记录为无序序列.接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直至最后一个记录插入到有序序列 ...
- 谷歌、腾讯、百度相应API批量获取地理位置坐标信息及其优缺点
目录: 申请ak 批量获取地理位置 目的:通过给定的地理位置名称(如:北京市海淀区上地十街十号),获取经纬度信息. 1.申请ak 以百度Geocoding API为例:http://lbsyun.ba ...
- ListView属性及divider设置分割线
给ListView设置分割线,只需设置如下两个属性: android:divider="#000" //设置分割线显示颜色 android:dividerHeight=" ...