WinForm/ASP.NET上使用实践 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所需要的属性和接口。代码很简单我这里就不多费口水代码如下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).Clicknew 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进行关联否则反之具体代码如下:[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和ViewModelusing 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(); } } }现在我们就可以运行程序在两个输入框分别输入中文名字和英文名字然后按下“显示”按钮就得到如下的结果[ViewModel(true)] 上面执行的结果是正确的那么现在改为[ViewModel(false)] 呢 先看下面代码和运行效果//通过Attributes的方式来标记,true表示关联false表示不关联具体由主程序控制 [ViewModel(false)] public partial class Form1 : Form { public Form1() { InitializeComponent(); } }执行的结果是没有命令被触发, 因为View Model 没有被激活也就是说View和ViewModel没有进行关联。 在ASP.NET中实现此模式我就不多进行阐述了如果大家有兴趣也可以做一