随着WPF/Silverlight等技术的出现,一种新的模式出现在大家面前,那就是MVVM,提到这个模式,大家也许感觉很迷惑,也许会不屑于故,也许你会说我现在做项目都形成了自己的框架了,为什么还要花费额外的时间和精力去学习这个MVVM模式呀?这个模式到底能给我们带来什么样的好处?那么我们本篇也会简单提及,由于这个会在WPF 基础到企业应用系列索引 里详细讲解,所以今天只是走马观花了解一下基本概念。
  一. 摘要
  众所周知,这个模式大量用在WPF/Silverlight上,但没有听说过用在Windows Form、ASP.NET等传统技术上。正是基于这个原因,我也对此进行了一些研究,做了一些Demo,但总体感觉在其他技术上不太适合,就一直没有管它了,直至有一天看到Bechir Bejaoui 也有这种思想,并且他打算在WinForm和ASP.NET项目当中使用,这使我感到有必要写一篇这方面的文章看看到底是否可行,正是基于这个原因,今天我们就用一个简单的例子来谈谈它在WinForm平台的应用,看看大家对这个有什么看法.
  二. 本文提纲
  · 1.摘要
  · 2.本文提纲
  · 3.MVVM基本介绍
  · 4.WPF/Silverlight项目中如何使用
  · 5.WinForm/ASP.NET上使用实践
  · 6.本文总结
  三. MVVM基本介绍
  WPF和Silverlight来了,它带来了3D、动画、音频视频……这导致了UI的变化将更加细节化和可定制化。同时,在技术层面上,WPF和Silverlight也带来了诸如Binding、 Dependency Property、Routed Events、Command、Attached Behavior(间接实现)、DataTemplate、ControlTemplate等新特性。我们怎样才能立足于原有的技术框架、把WPF/Silverlight的新特性揉合进去,以应对客户日益复杂且多变的需求呢?那么MVVM模式就是一个不错的选择。
  在MVVM模式中,你需要一个为View量身定制的model,那么这个model实际上就是上图ViewModel。ViewModel包含所有UI所需要的接口和属性,这样只需要通过Binding使他们进行关联,就可以使二者之间达到松散耦合,所以这样一来,UI就可以由UI专业人员用design和blend来实现(当然很多效果还是需要用传统的制图软件),代码人员也可以专心写他的逻辑也业务代码,所以这样分工和协作变得更轻松、更愉快了,更漂亮的是View完全可以由(Unit/Automatic Test)所取代,所以单元测试也变得如此简单,这对于我们的开发人员和测试人员无疑是一个很好的解脱,同时也提高了系统的可测性、稳定性和维护性。数据绑定系统同时也提供了标准化的方式传输到视图的验证错误的输入的验证(但是个人觉得不是很好用,所以我们在实际的项目当中会写一套自己的验证框架)。
  当然是用这个模式的时候,我们还要注意很多细节,这个是我们必须面对的,比如我们怎么实现ViewModel之间的通信、怎样用Attached Behavior实现特定命令操作、validation的自定义设置、延迟加载、性能优化、与传统技术的交互等等问题。
  四. WPF/Silverlight项目中如何使用
  1.我们的WPF/Silverlight项目
  前面讲了一些MVVM的基本概念,那么我们在WPF和Silverlight中究竟怎么使用呢?那么下面就是我们在项目当中的具体使用,第一幅图就是整个项目的结构图,第二副图是View和ViewModel以及一些常用的UI操作(当然这里也可以更加细节化,具体更加实际决定) 。
  上图就是整个项目的结构图
  上图是View和ViewModel以及一些常用的UI操作
  由于这个不是今天的重点,所以就不在这里阐述,以后有空会单独讲解。

2.我对架构的一些看法
  前两天我在一篇叫“ [征集].NET软件设计经验----期待你的参与”的帖子中回复了我对项目的一点微薄见解,或许很多是自己的一些错误观念,但是不交流的话,永远就不知道自己是对是错了,所以这里也贴出来,当然架构设计也不要过度,只要适宜即可,这也是我现在最大的体会。
  回顾过去,由于项目和公司原因,自己零零碎碎的什么都在做,什么都不精,也不敢在这里谈经验,只是自己的体会,望各位高手见谅,其他平台很菜,就不说了,对.Net平台感觉刚入门,从WinForm、ASP.NET(ASP.NET MVC一个项目没做完就被终止)到WPF和Silverlight,以至于到现在做的Windows Azure,不论是采用什么技术,最基本的东西都不会变,比如对数据库、文件和其他设备的访问、对日志和异常的处理、对数据结构的处理、对报表的展现、对打印的实现、对性能的提升、对数据的处理、对用户友好等等。
  那么这些项目也为我们积累了不少经验,有技术上的也有其他方面的:
  * 为了应付项目需求的不断变化和项目的可扩展性,我们也会引入OO和设计模式;
  * 为了解除各模块和组件的耦合,我们也会利用IOC的思想解耦;
  * 为了让逻辑代码清晰且没有其他代码的干扰,我们也会采用AOP的方式进行代码重组;
  * 为了解决诸如莫名奇妙的内存错误、Invoke异常,我们也会去研究晦涩难懂的CLR&IL,问题出了,你负责这个项目,必须得解决。
  * 为了使项目的开发速度更快且更方便,我们也会引入ORM思想来加快项目的开发速度和可维护性;
  * 为了更好组织各层开发,隔开耦合,我们也会采用MVC、MVP、MVVM模式;
  * 为了提升用户的响应速度,我们会采用AJAX的方式来实现;采用异步编程去解决用户漫长的等待问题;
  * 为了降低系统的负载同时提高用户的响应能力,我们也会采用MSMQ或者SSB来组织消息队列;
  * 为了企业业务整合,用户只需要登录一次就可以访问所有相互信任的应用系统,我们也会写一套自己的SSO;
  * 各种应用程序、各种服务的交错会让我们感到手足无措,为了规范各系统的接口,提供一个统一的交互平台,我们也会采用SOA;
  * 针对大量数据量实时处理、较高计算,解除用户等待的漫长等待,为了降低服务器的负担和提高速度,我们也会自己写一套缓存,并保证缓存的正确的更新与去除;
  * 为了把产品做好,我们也会不断优化技术直至达到期望的效果;
  * 为了能做好外包项目,我们会不需要任何高深技术,首先给客户期望的效果;
  * 为了能得到客户满意老板好评,我们也会学会如何交流,要明白最终是要得到客户的满意度,要得到money;
  其实归根到底就是要分清关系,理清思绪,既要处理好与机器的关系,也要处理好与人的关系,只有这样才能把产品或者项目做成功,项目做成功了,才有后面的发展和晋升,我也在不断学习当中,始终感觉自己是菜鸟,回头望去猛然发现自己又回到了原点,只有不断学习,不断进步了!
  五,WinForm/ASP.NET上使用实践
  1, 第一步
  WinForm和ASP.NET在使用这个模式的时候颇为类似,所以我们今天就用WinForm进行演示,为了能够更好的表达今天的主题,我们尽量把UI和逻辑做简单一些,这样便于我们要阐述的思想也能大道至简,首先我们先建立一个WinForm的项目,然后加入两个TextBox,五个Label,一个Button,控件的摆放位置如下所示:
然后我们新建三个文件夹,Common文件夹放一些公用的类,这里只放了ViewModelAttribute 类,其目的在于关联ViewModel和View的标示;View文件夹放置我们刚才新建的窗体,主要做UI的相关操作;ViewModel主要是放置一些ViewModel类(这些类是和View最好一一对应,提供一个定制化的Context).ClassDiagram1.cd是本应用程序的类图关系,Program.cs则承担了启动应用程序、关联View和ViewModel、处理整个应用程序的作用。

2,第二步
  第二步就是该建立我们的ViewModel了,我们在WPF中通常是一个View有一个定制的ViewModel相对应(或者多个View对应一个ViewModel),我们今天做的这个WinForm的例子也不例外,请看下面ViewModel类图:
正如我们上图看到的那样, View model 类包含了一个_form1的变量,这个变量的目的就是通过form1来操作它的子控件,然后我们就可以对它及它的子控件进行一些操作,已完成我们需要的业务,正如WPF/Silverlight中的ViewModel 一样,它的主要任务是提供给View的一个定制化的Model,所以我们要在里面实现业务的操作以及提供View所需要的属性和接口。代码很简单,我这里就不多费口水,代码如下:
#div_code img{border:0px;}using System;
using System.Windows.Forms;
namespace MVVMInWinForm
{    public class ViewModel   
{        //Form1的实例设置为View       
Form1 _form1;        
public ViewModel(Form1 form1)        {            _form1 = form1;       
     /*通过搜索整个页面的Controls,然后对各个控件的事件进行订阅 */         
foreach (Control item in _form1.Controls)       
{             
   if (item is Button)                {                     
(item as Button).Click+=new EventHandler(ViewModel_Click);           
     }          
  }         
   //启动窗体      
Application.Run(_form1);      
  }     
   ///<summary>   
     /// 具体的事件处理代码      
  /// </summary>      
  protected void ViewModel_Click(object sender, EventArgs args)      
  {         
   string result =string.Empty;      
      //具体操作         
   foreach (Control item in _form1.Controls)        
    {                
if (item is TextBox)                {                  
  result += (item as TextBox).Text;          
   
   }      
      }       
     foreach (Control item in _form1.Controls)            {             
   /* 显示操作后的结果*/             
if (item is Label && item.TabIndex ==5)            
    {                 
   (item as Label).Text = result.ToString();              
  }         
   }      
  }    
}    
   }
    3,第三步
  第三步是可选的步骤,你可以不用这个Attribute ,同样可以实现我们所要的功能,但加上它以后可以增强程序的灵活性。我们通过反射的形式来读取值,然后标示View是否被激活,如果是,则View和ViewModel进行关联,否则反之;
具体代码如下:
#div_code img{border:0px;}[global::System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]sealed class ViewModelAttribute : System.Attribute
{    
public ViewModelAttribute() 
{
}   
public ViewModelAttribute(bool Activated)    {       
this.Activated = Activated;  
  }       
public bool Activated { get; set; }
}

4,第四步
  第四步很重要,Winform中不像WPF和Silverlight那样灵活且没有那么多的延伸特性和附加功能,所以只能通过外界代码的方式手动绑定View和ViewModel
#div_code img{border:0px;}using System;using System.Reflection;using System.Windows.Forms;using MVVMInWinForm.Attribute;namespace MVVMInWinForm{    
static class Program    
{        
[STAThread]        
static void Main()        {           
Application.EnableVisualStyles();            Application.SetCompatibleTextRenderingDefault(false);          
  Initialize();       
}       
private static void Initialize()        {           
Type t = typeof(Form1);       
  //通过Type获取Attributes的值     
object[] attributes = t.GetCustomAttributes(typeof(ViewModelAttribute), 
false);       
//如果ViewModelAttribute的Activated值为true,把相关的View和ViewModel关联起来,否则不关联            if (attributes.Length > 0 && (attributes[0] as ViewModelAttribute).Activated == true)          
  {               
Form1 form1 = new Form1();                ViewModel viewModel = new ViewModel(form1);        
    }          
  else         
   {               
Application.Run(new Form1());       
     }       
}        
}
}
   5,第五步
  第五步我们需要给Form1类加上一个Attribute,其目的是增加View和ViewModel的灵活性,使他们可以松散耦合、灵活配置,如下代码:
#div_code img{border:0px;}using System;using System.Windows.Forms;
using MVVMInWinForm.Attribute;namespace MVVMInWinForm{    
//通过Attributes的方式来标记,true表示关联,false表示不关联,具体由主程序控制    
[ViewModel(true)]    
public partial class Form1 : Form    
{       
public Form1()      
  {           
InitializeComponent();       
}   
}
}
   现在我们就可以运行程序,在两个输入框分别输入中文名字和英文名字,然后按下“显示”按钮,就得到如下的结果:
[ViewModel(true)] 上面执行的结果是正确的,那么现在改为[ViewModel(false)] 呢? 先看下面代码和运行效果:
#div_code img{border:0px;}//通过Attributes的方式来标记,true表示关联,false表示不关联,具体由主程序控制
[ViewModel(false)]
public partial class Form1 : Form
{   
public Form1()  
  {        
InitializeComponent(); 
   }
}

执行的结果是没有命令被触发, 因为View Model 没有被激活,也就是说View和ViewModel没有进行关联。 在ASP.NET中实现此模式我就不多进行阐述了,如果大家有兴趣也可以做一个Demo试试,原理基本一样。
  六.本文总结:
  今天我们从MVVM基本介绍讲起,然后概览了我们在WPF/Silverlight项目中如何使用这个模式以及在WinForm/ASP.NET上的使用实践,通过今天的这篇文章,我个人觉得MVVM模式是WPF/Silverlight下的产物,所以运用起来也非常得心应手,在其他平台上使用有诸多局限。在WinForm/ASP.NET上的使用并不能带来什么好处,反而增加了工作量和成本系数,所以我个人还是不太推荐这样使用,不知道大家有什么看法,写篇文章也是怀着技术交流的心态发布出来,由于是自己对这些技术的使用总结和心得体会,错误之处在所难免,所以希望大家能够多多指点,这样也能纠正我的错误观点,以便和各位共同提高!
  由于思维发散的缘故,每写一篇文章,从构思到Demo和文章前后要几天时间,不知道大家在写文章有这样的体会没有,也许是自己知识浅薄的缘故才会这样吧。最后如果大家感兴趣,也可以关注WPF 基础到企业应用系列索引这个系列文章,我也会不定期的逐渐更新,谢谢各位的关注,也欢迎和各位交流讨论。

转载于:https://blog.51cto.com/apprentice/1360646

WPF/Silverlight中MVVM运用相关推荐

  1. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十二) 雷、混、冰、毒、火、风 - 幻化中的魔法魅力!...

    魔法的魅力不仅仅因为其华丽的外表,更深层次的,它们的额外附加属性效果使得游戏世界更加幻化多彩!无论是中式的金木水火土5行,还是欧式的水火风雷,异或是日式的风林火山等等,在目前的网游世界中无处不得到体现 ...

  2. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十五)完美捕捉精灵之神器 -- HitTest...

    怪物们都出现了,如何选中自己心仪的怪是主角目前首要做的事. 为了进行鼠标状态区别,我首先对鼠标变化规则进行约束:当鼠标在屏幕上空旷地图区域移动时,鼠标光标形态表现为默认光标 (0号光标图片),当鼠标经 ...

  3. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十)斜度α地图的构造及算法...

    在当前的网络游戏中,地图基本都是采取一定斜度的拼装地图,这其中存在两种斜度地图的构造方式: 第一种我称之为伪斜度地图:该类型地图表现层图片为斜度的,但地图基底障碍物等的构造则实为正方形,如下图: 其实 ...

  4. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十一)地图遮罩层的实现

    前面的章节主要针对地图表现层进行讲解.通常来说,简单的游戏光有它就足够了:但是为了达到更加真实的光影效果,模拟真实的虚拟世界,我们还得继续在地图上下大工夫.本节将就如何实现地图中的遮罩层,即物体对角色 ...

  5. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十四) 精灵控件横空出世!①

    在上一节中,我们实现了地图牵引式移动,同时还遗留着一个小尾巴:主角和障碍物该如何跟随着地图的移动而移动? 上节中有点到,只要在地图移动的同时,时时根据主角等对象物体的X,Y坐标进行相对于地图的X,Y坐 ...

  6. C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(十四) 精灵控件横空出世!①

    在上一节中,我们实现了地图牵引式移动,同时还遗留着一个小尾巴:主角和障碍物该如何跟随着地图的移动而移动? 上节中有点到,只要在地图移动的同时,时时根据主角等对象物体的X,Y坐标进行相对于地图的X,Y坐 ...

  7. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十一) 超酷万变的矢量魔法...

    还记得当年的经典网游奇迹(MU)吗?辉煌就如同其名字一般深刻烙印在我的脑海.与朋友们一起通宵奋战的日子已成过去,残留世上那一张张经典不朽的截图让我时刻感受回味.它的成功不仅仅因为其拥有一个极棒的世界观 ...

  8. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十一) 超酷万变的矢量魔法

    还记得当年的经典网游奇迹(MU)吗?辉煌就如同其名字一般深刻烙印在我的脑海.与朋友们一起通宵奋战的日子已成过去,残留世上那一张张经典不朽的截图让我时刻感受回味.它的成功不仅仅因为其拥有一个极棒的世界观 ...

  9. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十六)通用型角色头像面板...

    目前游戏的开发进度已经基本实现了精灵对象之间的普通交互,接下来我们需要朝着实现战斗系统的目标前行.而实现它的前提是必须完善精灵控件的基本属性,如添加生命值.魔法值.活力值.经验值等基本属性并通过窗体界 ...

最新文章

  1. jdbcdslog hibernate sql log
  2. Docker 制作镜像-redis
  3. VS2008 error RC2170: bitmap file xxx.png is not in 3.00 format(转)
  4. 前端ui 后台管理系统 简洁_Github上前端不可不知的可视化后台管理系统(1)
  5. hive 导入mysql数据库_求助 Hive 导入MYsql 数据库 报错啊
  6. Request/Response
  7. java中cleanup的使用_Eclipse使用代码清理功能(Clean Up)
  8. dell服务器r730老自动重启_Dell R730服务器安装windows server 2008 R2蓝屏问题
  9. 谁在阻止RSS的普及??
  10. nyoj_49_开心的小明_201403161133
  11. 程序员思维训练500题(附带答案)
  12. Qt-高分辨率drawImage模糊问题
  13. 从混沌熬到风口:移动FM的五年之争
  14. Arduino UNO驱动液晶屏TFT_LCD_ST7789v
  15. 新东方 词根词缀 excel_背单词 | 新东方的杨鹏老师用什么方法?
  16. colab设置成英文
  17. python pip安装pymssql_pip安装pymssql模块时报错“PEP 517”怎样处理
  18. ue4-UMG和HUD绘制UI
  19. 【程序厨】学习 Redis ,可以看看这个
  20. 闲聊互联网经济的现代化

热门文章

  1. kafka python教程_由Flink与Kafka实践探究Kafka的两个问题
  2. CSS 分组 和 嵌套 选择器
  3. raster | 栅格对象如何用于非空间模型的预测?
  4. 2021年跨专业/转行业学IT,还有前途吗?
  5. 一行能装逼的JavaScript代码,就是怎么sao
  6. 排序算法java快速排序_快速排序算法--Java实现
  7. python3导入模块原理_python模块导入原理
  8. mongodb连接池 php,node.js,mongodb_nodejs使用mongodb连接池,node.js,mongodb - phpStudy
  9. android 百叶窗动画,android 幻灯片效果之百叶窗
  10. Linux学习笔记---使用MfgTool工具烧写自己的系统(二)