`
380071587
  • 浏览: 507806 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

WPF/Silverlight中的MVVM模式能否在WinForm/ASP.NET上运用?

 
阅读更多

一. 摘要

  随着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模式就是一个不错的选择。

mvvmModel

  在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操作(当然这里也可以更加细节化,具体更加实际决定) 。

Arc1

上图就是整个项目的结构图

Arc2

上图是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,控件的摆放位置如下所示:
7-26-2010 12-31-11 AM
  然后我们新建三个文件夹,Common文件夹放一些公用的类,这里只放了ViewModelAttribute 类,其目的在于关联ViewModel和View的标示;View文件夹放置我们刚才新建的窗体,主要做UI的相关操作;ViewModel主要是放置一些ViewModel类(这些类是和View最好一一对应,提供一个定制化的Context).ClassDiagram1.cd是本应用程序的类图关系,Program.cs则承担了启动应用程序、关联View和ViewModel、处理整个应用程序的作用。

2

2,第二步

  第二步就是该建立我们的ViewModel了,我们在WPF中通常是一个View有一个定制的ViewModel相对应(或者多个View对应一个ViewModel),我们今天做的这个WinForm的例子也不例外,请看下面ViewModel类图:
2.gif
  正如我们上图看到的那样, View model 类包含了一个_form1的变量,这个变量的目的就是通过form1来操作它的子控件,然后我们就可以对它及它的子控件进行一些操作,已完成我们需要的业务,正如WPF/Silverlight中的ViewModel 一样,它的主要任务是提供给View的一个定制化的Model,所以我们要在里面实现业务的操作以及提供View所需要的属性和接口。代码很简单,我这里就不多费口水,代码如下:

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进行关联,否则反之;


3.gif
具体代码如下:

[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

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的灵活性,使他们可以松散耦合、灵活配置,如下代码:

using System;
using System.Windows.Forms;
using MVVMInWinForm.Attribute;

namespace MVVMInWinForm
{
//通过Attributes的方式来标记,true表示关联,false表示不关联,具体由主程序控制
[ViewModel(true)]
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}


  现在我们就可以运行程序,在两个输入框分别输入中文名字和英文名字,然后按下“显示”按钮,就得到如下的结果:
7-26-2010 12-31-59 AM
  [ViewModel(true)] 上面执行的结果是正确的,那么现在改为[ViewModel(false)] 呢? 先看下面代码和运行效果:

//通过Attributes的方式来标记,true表示关联,false表示不关联,具体由主程序控制
[ViewModel(false)]
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}


7-26-2010 12-33-00 AM
  执行的结果是没有命令被触发, 因为View Model 没有被激活,也就是说View和ViewModel没有进行关联。 在ASP.NET中实现此模式我就不多进行阐述了,如果大家有兴趣也可以做一个Demo试试,原理基本一样。

六.本文总结:

  今天我们从MVVM基本介绍讲起,然后概览了我们在WPF/Silverlight项目中如何使用这个模式以及在WinForm/ASP.NET上的使用实践,通过今天的这篇文章,我个人觉得MVVM模式是WPF/Silverlight下的产物,所以运用起来也非常得心应手,在其他平台上使用有诸多局限。在WinForm/ASP.NET上的使用并不能带来什么好处,反而增加了工作量和成本系数,所以我个人还是不太推荐这样使用,不知道大家有什么看法,写篇文章也是怀着技术交流的心态发布出来,由于是自己对这些技术的使用总结和心得体会,错误之处在所难免,所以希望大家能够多多指点,这样也能纠正我的错误观点,以便和各位共同提高!

  由于思维发散的缘故,每写一篇文章,从构思到Demo和文章前后要几天时间,不知道大家在写文章有这样的体会没有,也许是自己知识浅薄的缘故才会这样吧。最后如果大家感兴趣,也可以关注WPF 基础到企业应用系列索引这个系列文章,我也会不定期的逐渐更新,谢谢各位的关注,也欢迎和各位交流讨论。

分享到:
评论

相关推荐

    C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial 前38节)

    C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(九)2D游戏角色在地图上的移动 C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十)斜度α地图的构造及算法 C#开发WPF/Silverlight动画及...

    WPF与Silverlight的MVVM模式教程

    ### WPF与Silverlight的MVVM模式教程:深入解析与实战指南 #### 一、MVVM模式概览 ...对于那些寻求在WPF和Silverlight环境中构建高质量、高性能的应用程序的开发者来说,掌握MVVM模式是必不可少的技能之一。

    WPF / Mvvm模式及MVC模式示例

    本示例将探讨两种常用的设计模式:Model-View-ViewModel (MVVM) 和 Model-View-Controller (MVC),它们在C# WPF应用程序中的应用。 **1. Model-View-Controller (MVC) 模式** MVC模式是一种经典的分层设计模式,...

    Pro WPF and Silverlight MVVM-English

    It is now recognized that any non-trivial WPF or Silverlight application needs be designed around the Model-View-ViewModel (MVVM) design pattern in order to unlock the technology's full data-binding ...

    C#开发的WPF/Silverlight游戏

    我将在本教程中完全屏弃它所有的弱点,实现它未实现的所有功能,让所有的朋友们均能用WPF/Silverlight进行游戏深度开发 可以通过对App.xaml的StartupUri参数进行修改,实现不同的Window启动首选项 如果编译不通过...

    WPF-MVVM WPF MVVM模式开发的例子程序

    在WPF-MVVM模式开发中,开发者可以利用XAML语言来声明式地定义视图,同时利用C#或其他.NET编程语言编写视图模型。数据绑定使得视图中的UI元素可以直接与视图模型的属性关联,当属性值改变时,视图会自动更新;反之,...

    wpf/silverlight读取shapefile文件类

    标题中的“wpf/silverlight读取shapefile文件类”是指在Windows Presentation Foundation (WPF)和Silverlight这两个Microsoft的开发框架中,实现读取地理信息系统(GIS)中常用的Shapefile格式的代码类。Shapefile是...

    WPF/SilverLight 代码

    在**C#**中使用WPF和Silverlight,开发者可以利用C#的强大特性和.NET Framework的类库来编写后端逻辑。C#是一种类型安全、面向对象的编程语言,它提供了诸如自动垃圾回收、匿名方法、lambda表达式、LINQ(Language ...

    WPF MVVM 模式使用DataGrid

    在Windows Presentation Foundation (WPF) 中,MVVM(Model-View-ViewModel)是一种设计模式,它将业务逻辑、用户界面和数据模型分离,使得代码更易于维护和测试。本篇文章将详细探讨如何在MVVM模式下有效地使用...

    【ASP.NET编程知识】在WinForm和WPF中使用GMap.Net地图插件简单教程.docx

    ASP.NET编程知识之GMap.Net地图插件在WinForm和WPF中的应用 GMap.Net是一款功能强大且灵活的地图插件,它可以在WinForm和WPF应用程序中使用,以提供丰富的地图显示和交互功能。下面我们将详细介绍如何在WinForm和...

    WPF .net4.5 +MvvmLight +Sqlite 实现数据增加删除即时更新到datagrid,源码

    在本项目中,开发者使用了WPF(Windows Presentation Foundation)技术,配合.NET Framework 4.5,MvvmLight(Model-View-ViewModel Light)设计模式,以及SQLite数据库,实现了一个简单但实用的数据管理应用程序。...

    WPF经典编程实例/C#/.NET/MVVM/WCF/XAML/WinForm

    本课程通过一个个实战的案例,详细介绍了在WPF编程中用到的各种技巧,帮你进一步掌握WPF这种优秀的编程框架。也许你曾经为了一个WPF又酷又炫的功能,查遍资料却终无所获,最后无奈遗憾放弃。如果你学习了这门课程,...

    Pro WPF and Silverlight MVVM

    《Pro WPF 和 Silverlight MVVM》是一本全面介绍 MVVM 设计模式及其在 WPF 和 Silverlight 开发中应用的书籍。通过详细解释 MVVM 的各个方面,本书不仅适合初学者入门,也为有经验的开发者提供了深入的理解和技术...

    MVVM在Winform应用实例

    MVVM是一种软件架构模式,它在WPF和UWP等现代UI框架中广泛使用,但在Winform中相对较少见,因为Winform本身并不直接支持数据绑定和依赖属性。这个实例可能展示了如何在Winform环境中手动实现或模拟MVVM模式。 **...

    WPF/Silverlight 开关按钮 开源DLL

    在本文中,我们将深入探讨WPF(Windows Presentation Foundation)和Silverlight中的开关按钮控件,以及如何使用开源DLL实现这一功能。"Toggle Switch Control Library"是开发者社区共享的一个资源,它提供了一个...

    C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial 50节全)

    5. **数据绑定和MVVM模式**:理解数据绑定的概念,如何将UI与数据模型连接起来,以及MVVM(Model-View-ViewModel)设计模式在WPF中的应用。 6. **Silverlight特定特性**:探索Silverlight特有的API和功能,如...

    wpf中MVVM模式下窗体跳转及显隐控制实现

    在Windows Presentation Foundation (WPF)开发中,MVVM(Model-View-ViewModel)设计模式是一种广泛应用的架构模式,它将用户界面(View)、业务逻辑(ViewModel)和数据模型(Model)进行分离,使得代码更易于测试...

Global site tag (gtag.js) - Google Analytics