原文:WPF MVVM从入门到精通1:MVVM模式简介

WPF MVVM从入门到精通1:MVVM模式简介

WPF MVVM从入门到精通2:实现一个登录窗口

WPF MVVM从入门到精通3:数据绑定

WPF MVVM从入门到精通4:命令和事件

WPF MVVM从入门到精通5:PasswordBox的绑定

WPF MVVM从入门到精通6:RadioButton等一对多控件的绑定

WPF MVVM从入门到精通7:关闭窗口和打开新窗口

WPF MVVM从入门到精通8:数据验证

完整示例代码下载LoginDemo

刚开始接触和使用MVVM模式的时候,就有一种感觉:哇,实现这么一丁点的功能,竟然要写这么多代码,太麻烦了吧!但是后来当我熟悉了这种模式之后,感觉就变成了:哇,还是这么麻烦。

没错,使用MVVM模式的确要在项目中增加很多代码。不过MVVM设计模式是有它的优点的,不然就不会存在。把界面和业务逻辑分离,这是MVVM的根本目的。WPF的依赖属性、数据绑定等机制,很好地帮助我们实现MVVM模式,基本可以做到在界面层不出现业务逻辑代码。

我们先来看一下MVVM模式的基本结构:

View就是界面,可以理解为XAML文件创作的内容。

Model是数据,是界面需要的数据。有人会在Model这一层里加入少量的逻辑代码,但我认为,这样破坏了Model的纯净性。

最复杂的内容都放在ViewModel里面。很多时候,逻辑代码也是可以分层、分块的,可以把这些代码放在一个辅助类库里面,然后ViewModel去调用它。

一般情况下,一个View对应一个ViewModel和一个Model。但在某些场合可以适当调整。例如,界面中某些数据是需要保存到文件的,某些只是辅助界面的显示而已,这时候,我们可以使用多个Model去存放。

最理想的情况下,实现MVVM模式后,跟View关联的CS文件会是如下面的代码所示:

using LoginDemo.ViewModel.Login;
using System.Windows; namespace LoginDemo
{
/// <summary>
/// LoginWindow.xaml 的交互逻辑
/// </summary>
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent(); this.DataContext = new LoginViewModel();
}
}
}

对,其实就是在自动生成的代码里面加入了this.DataContext = new LoginViewModel();这一行。除此之外,这个文件再没有其他代码了。而实际上(带有个人想法),在一般的项目中,后台代码都没必要这么简洁。有些界面操作,是非常固定的,没必须写一大堆代码来实现。例如点击一个按钮就关闭窗口,这个功能没必要关联命令、关联事件去实现了。

我们同时从上面的代码看出,View和ViewModel的交互是通过DataContext这一对象来完成的。先上图:

在View里面,存在着大量的绑定语句。例如,用户名输入框绑定了名称为UserName的属性,性别男单选框绑定了属性Gender,当它的值为1时显示为选中。当然,我们也希望动作可以反过来。也就是在用户名输入框改变文字时,UserName也相应地改变,点击性别男时,Gender被设为1。在View里面,不需要写任何后台代码,只通过绑定就能完成前面所说的功能。有趣的是,UserName和Gender这两个属性究竟在哪里定义(甚至不一定存在),View是不关心的。它一直在等待着消息,当有人告诉它,UserName已经改成XXX了,它马上把输入框的内容改成XXX。当用户在输入框里输入OOO时,它就像广播一样,大声地喊:UserName要改成OOO了。究竟有没有人听到并做出处理呢?它并不关心。

ViewModel里面定义了大量的依赖属性。当这些属性改变时,它们会触发一个属性更改的通知事件。例如UserName="XXX";这个语句执行后,ViewModel就像广播一样大声地喊:UserName改成XXX了!同样的,有没有人听到,如何处理,它都不关心。

如此我们可以看到,在开始一个项目之前,只要我们把界面草图画好,功能大致确定好,程序员和美工就可以分头行事,各干各的了。这就是MVVM模式要做到的事情。

在后面的登录界面例子中,我们将一步步实现一个比较理想的MVVM模式程序。

 

最新文章

  1. easyUI的基础布局easyui-accordion
  2. jQuery-DataTables相关的网址
  3. 【开源】OSharp框架解说系列(1):总体设计及系列导航
  4. [gist]在浏览器里免查看源代码格式化var_dump输出
  5. jQuery入门级part.1
  6. ASP.NET MVC学习之模型模板篇
  7. pod install 错误 - incompatible character encodings: UTF-8 and ASCII-8BIT
  8. 【转】PackageInfo、ResolveInfo 笔记
  9. Linux之select系统调用_2
  10. js的for in具有不适应性(转)
  11. 远控软件VNC攻击案例研究
  12. 如何创建一个自定义jQuery插件
  13. poj3177 Redundant Paths
  14. c# webBrowser 获取Ajax信息 .
  15. BASE64URL解析
  16. [转载] OAuth2.0认证和授权原理
  17. SLAM+语音机器人DIY系列:(四)差分底盘设计——5.底盘PID控制参数整定
  18. Day 4-9 subprocess模块
  19. [CC-CLPOINT]Optimal Point
  20. Java代码一行一行读取txt的内容

热门文章

  1. Mysql中的char与varchar length()与char_length()
  2. ZooKeeper学习之路 (四)ZooKeeper开发环境eclipse配置
  3. js 键盘点击事件
  4. 安装Centos 7 错误解决
  5. sqoop2启动client异常
  6. LORA芯片SX1272IMLTRT资料介绍
  7. backtype.storm.generated.InvalidTopologyException:null问题的解决
  8. 字符型设备驱动程序-first-printf以及点亮LED灯(一)
  9. EF Core中外键关系的DeleteBehavior介绍(转自MSDN)
  10. Source folder is not on the Java build class path