WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
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。第一个方法可以让我们来判断是否可以执行这个命令,第二个方法就是我们具体的命令。

1 using System;
2
3 using System.Collections.Generic;
4
5 using System.Linq;
6
7 using System.Text;
8
9 using System.Windows.Input;
10
11
12
13 /***********************作者:黄昏前黎明后**********************************
14
15 * 作者:黄昏前黎明后
16
17 * CLR版本:4.0.30319.42000
18
19 * 创建时间:2018-04-05 22:57:56
20
21 * 命名空间:Example3
22
23 * 唯一标识:b9043d4c-fdd7-4e0f-a324-00f0f09286d0
24
25 * 机器名称:HLPC
26
27 * 联系人邮箱:hl@cn-bi.com
28
29 *
30
31 * 描述说明:
32
33 *
34
35 * 修改历史:
36
37 *
38
39 *
40
41 *****************************************************************/
42
43 namespace Example3
44
45 {
46
47 public class RelayCommand : ICommand
48
49 {
50
51 #region 字段
52
53 readonly Func<Boolean> _canExecute;
54
55 readonly Action _execute;
56
57 #endregion
58
59
60
61 #region 构造函数
62
63 public RelayCommand(Action execute)
64
65 : this(execute, null)
66
67 {
68
69 }
70
71 public RelayCommand(Action execute, Func<Boolean> canExecute)
72
73 {
74
75 if (execute == null)
76
77 throw new ArgumentNullException("execute");
78
79 _execute = execute;
80
81 _canExecute = canExecute;
82
83 }
84
85 #endregion
86
87
88
89 #region ICommand的成员
90
91 public event EventHandler CanExecuteChanged
92
93 {
94
95 add
96
97 {
98
99
100
101 if (_canExecute != null)
102
103 CommandManager.RequerySuggested += value;
104
105 }
106
107 remove
108
109 {
110
111
112
113 if (_canExecute != null)
114
115 CommandManager.RequerySuggested -= value;
116
117 }
118
119 }
120
121
122
123 [DebuggerStepThrough]
124
125 public Boolean CanExecute(Object parameter)
126
127 {
128
129 return _canExecute == null ? true : _canExecute();
130
131 }
132
133
134
135 public void Execute(Object parameter)
136
137 {
138
139 _execute();
140
141 }
142
143 #endregion
144
145 }
146
147 }
148
149

我们再在我们的NameViewModel中声明一个ICommand字段:

1 #region 命令
2
3 void UpdateNameExecute()
4
5 {
6
7 this.UserName = "黄昏前黎明后";
8
9 this.CompanyName = "中软易通科技";
10
11 }
12
13
14
15 bool CanUpdateNameExecute()
16
17 {
18
19 return true;
20
21 }
22
23
24
25 public ICommand UpdateName { get { return new RelayCommand(UpdateNameExecute, CanUpdateNameExecute); } }
26
27
28
29 #endregion

最后,我们再将事件绑定上这个Command:
<Button Content="更新" Command="{Binding UpdateName}" Margin="20"/>
运行一下,看结果。我们成功将事件分离了出来。

看到上面的结果,似乎目前为止我们已经很好的解决了所有的问题。我们看到运行的数据,事件都是绑定的,实现了界面的完美分离。实际在处理问题是好像需要考虑通用性,这时我们能否把MVVM提取出来作为一个框架,来去更好的解决问题。下一次我们一起来看看怎么进行提取成为通用框架。
本文的DEMO下载地址:WPFMVVMDemo2.zip
WPF自学入门(十)WPF MVVM简单介绍
前面文章中,我们已经知道,WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI。
我们不管是NET中还是WPF中使用模式目的就是想达到高内聚低耦合。在WPF开发中,经典的编程模式是MVVM,是为WPF量身定做的模式,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,甚至不用修改。与WinForm开发相比,我们一般在后置代码中会使用控件的名字来操作控件的属性来更新UI,而在WPF中通常是通过数据绑定来更新UI;在响应用户操作上,WinForm是通过控件的事件来处理,而WPF可以使用命令绑定的方式来处理,耦合度将降低。
一、MVVM介绍
MVVM是Model-View-ViewModel(模型-视图-视图模型)的缩写形式,它通常被用于WPF或Silverlight开发。我们可以通过下图来直观的理解MVVM模式:

1、View就是用xaml实现的界面,负责与用户交互,接收用户输入,把数据展现给用户。
2、ViewModel是一个C#类,负责收集需要绑定的数据和命令,聚合Model对象,通过View类的DataContext属性绑定到View,同时也可以处理一些UI逻辑。
3、Model,就是系统中的对象,可包含属性和行为。
三者之间的关系:View对应一个ViewModel,ViewModel可以聚合N个Model,ViewModel可以对应多个View
二、MVVM的优势
MVVM的根本思想就是界面和业务功能进行分离,View的职责就是负责如何显示数据及发送命令,ViewModel的功能就是如何提供数据和执行命令。各司其职,互不影响。在实际的业务场景中我们经常会遇到客户对界面提出建议要求修改,使用MVVM模式开发,当设计的界面不满足客户时,我们仅仅只需要对View作修改,不会影响到ViewModel中的功能代码,减少了犯错的机会。随着功能地增加,系统越来越复杂,相应地程序中会增加View和ViewModel文件,将复杂的界面分离成局部的View,局部的View对应局部的ViewModel,功能点散落在各个ViewModel中,每个ViewModel只专注自己职能之内的事情。ViewModel包含了View要显示的数据,并且知道View的交互代码,所以ViewModel就像一个无形的View。使用MVVM架构具有以下优势
1、易维护
2、灵活扩展
3、易测试
4、用户界面设计师与程序开发者能更好的合作
三、MVVM简单示例
为了让大家直观地了解MVVM的编程模式,下面会用到前面讲到的数据绑定以及命令等知识。
新建WPF项目,名称WPFMVVMDemo。添加用户类,如下图

在WPF术语中,这个叫“模型”,GUI是“视图”。不可思议的是“视图模型”,通过数据绑定将它们绑在一起,它真的是一个很好的适配器能将模型变成某种WPF框架可以使用的东西。所以这个就是“模型”。
接下来我们会非常容易理解创建视图模型:

请注意这个视图模型不是十分正确的。因为我们在视图模型里暴露了属性,我们显然会想使在代码里改变的用户名和公司名自动的显示在视图上

后台代码:

运行结果:

这里我们点击更新按钮不会有任何反应,因为还没有实现数据绑定。此时视图不会收到任何的关于属性改变的通知。要解决这个问题我们必须实现名称为INotifyPropertyChanged的接口。任何实现了这个接口的类,当属性发生改变的时候会通知所有监听者,所以我们需要修改视图模型NameViewModel类:

这里会产生多个事件。首先,我们检查了我们是否真的改变了属性。第二,如果值已经改变,我们向所有监听者注册PropertyChanged事件。现在我们有了一个模型Name和一个视图模型NameViewModel。我们只需要在定义视图。只需要修改视图MainWindow:

运行结果:

本文的demo下载地址:WPFMVVMDemo1.zip
WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍的更多相关文章
- WPF自学入门(十一)WPF MVVM模式Command命令
在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...
- 命令模式 Command 行为型 设计模式(十八)
命令模式(Command) 请分析上图中这条命令的涉及到的角色以及执行过程,一种可能的理解方式是这样子的: 涉及角色为:大狗子和大狗子他妈 过程为:大狗子他妈角色 调用 大狗子的“回家吃饭”方法 引子 ...
- WPF Prism框架下基于MVVM模式的命令、绑定、事件
Prism框架下的自定义路由事件和命令绑定 BaseCode XAML代码: <Button x:Class="IM.UI.CommandEx.PrismCommandEx" ...
- 十一个行为模式之命令模式(Command Pattern)
定义: 将一个请求封装成对象,使得请求发送者和请求接受者之间相互隔离,消除两者之间的耦合.引入命令类,使得不同请求对客户参数化,并且可以对命令添加附件操作,如:排队.撤销.日志.组合等. 结构图: C ...
- MVVM模式的命令绑定
命令绑定要达到的效果 命令绑定要关注的核心就是两个方面的问题,命令能否执行和命令怎么执行.也就是说当View中的一个Button绑定了ViewModel中一个命令后,什么时候这个Button是可用的, ...
- WPF MVVM模式的一些理解
/*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...
- WPF中使用MVVM模式进行简单的数据绑定
计划慢慢整理自己在WPF学习和工作应用中的一些心得和想法,先从一个简单的用法说起 在WPF中,XAML标记语言中绑定数据,而数据源就是指定为ViewModel类,而非界面本身的逻辑代码类 这样一定程度 ...
- MVVM模式应用体会
转自:http://www.cnblogs.com/626498301/archive/2011/04/08/2009404.html 进公司实习工作后,本人接触的第一个技术名语就是MVVM模式,从学 ...
- 什么是MVVM模式
问题引入1 场景一:团队辛辛苦苦完成了一个项目,抱着激动的心情去给用户做demo,而用户给你的反馈是UI很不满意,要重新修改,否则拒绝验收.大规模修改UI,晴天霹雳!2 场景二:产品在一家客户上线运行 ...
随机推荐
- POJ数据的输入输出格式
POJ在评阅习题时需要向程序提供输入数据,并获取程序的输出结果.因此提交的程序需按照每个习题具体的输入输出格式要求处理输入输出.有的时候,测评系统给出程序的评判结果是“数据错误”或“结果错误”,有可能 ...
- ssd训练自己的数据集
1.在ssd/caffe/data下创建VOC2007的目录,将ssd/caffe/data/VOC0712里的create_data.sh.create_list.sh和labelmap_voc.p ...
- Android全局异常捕获
PS:本文摘抄自<Android高级进阶>,仅供学习使用 Java API提供了一个全局异常捕获处理器,Android引用在Java层捕获Crash依赖的就是Thread.Uncaught ...
- extjs传递参数
以前我是这么传的: 先获取表Form,再通过表找组件,然后用gradeCode=0&groupCode=1传 现在只需要先获得表,然后通过form.getValues()取得所有的值,再使用E ...
- 全国高校绿色计算大赛 预赛第三阶段(Python)(随机数)
只提交了随机数 (真心不会 T-T ) import csv import random import pandas as pd import numpy as np # 预测结果文件:src/ste ...
- Hihocoder #1938 最大权闭合子图模板
这里的讲解很不错,适合作为入坑题: Hihocoder#1938 代码: #include<algorithm> #include<iostream> #include< ...
- Java的类加载
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是Java虚拟机的类加载机制 ----类加载的大致过程 类的加载的过 ...
- [Python3网络爬虫开发实战] 1.5.1-PyMySQL的安装
在Python 3中,如果想要将数据存储到MySQL中,就需要借助PyMySQL来操作,本节中我们介绍一下它的安装方式. 1. 相关链接 GitHub:https://github.com/PyMyS ...
- Memcache 分布式存储 【一致性Hash】crc32
class memcacheHash { private $_node = array(); private $_nodeData = array(); private $_keyNode = 0; ...
- scrapy实现全站抓取数据
1. scrapy.CrawlSpider scrapy框架提供了多种类型的spider,大致分为两类,一类为基本spider(scrapy.Spider),另一类为通用spider(scrapy.s ...