当前位置: 首页 > news >正文

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



具体代码如下:

[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(); } } }


现在我们就可以运行程序,在两个输入框分别输入中文名字和英文名字,然后按下“显示”按钮,就得到如下的结果:


[ViewModel(true)] 上面执行的结果是正确的,那么现在改为[ViewModel(false)] 呢? 先看下面代码和运行效果:

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



执行的结果是没有命令被触发, 因为View Model 没有被激活,也就是说View和ViewModel没有进行关联。 在ASP.NET中实现此模式我就不多进行阐述了,如果大家有兴趣也可以做一

http://www.gsyq.cn/news/1637359.html

相关文章:

  • Go 推理客户端:重试要懂模型调用的副作用
  • WebShell溯源实战:从CVI-360001告警到漏洞根因挖掘
  • HelloAgents:RAG——让 Agent 学会检索知识
  • 基于STM32单片机智能手环心率血氧体温GPS定位跌倒计步器系统设计12(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • 在浏览器里逛唐长安城,这个开源项目让我直接穿越了!
  • 记录arm64内核调试环境搭建qemu_arm64_linux_01
  • 漏扫发现-Web服务篇Poc开发Yakit插件编写Afrog项目Yaml语法Yak语言接受匹配
  • 《用AI做公众号流量主》第13课:为什么 99% 的人用 AI 生产的都是“电子垃圾”?
  • 手中有机, 心中不慌 (5 只 二手 Android 手机)
  • CTF ECC基础离散对数爆破 解题Writeup
  • Agent 云原生运行时:智能体也需要健康检查
  • Java毕设项目:中小型乡村民宿山庄综合业务管理系统的设计与实现 基于 Java 的民宿客户信息与消费记录管理系统 (源码+文档,讲解、调试运行,定制等)
  • AT 指令学习手册:从对话逻辑到实战排错
  • Avalonia NativeControlHost
  • CSS Cascade Layer:样式优先级要靠架构,不靠赌命名
  • 原神120帧解锁终极指南:免费提升游戏流畅度的完整教程
  • 服务器安全(Windows Server+Linux)
  • 基于STM32单片机车位引导 智能停车场计费系统 刷卡识别 WIFI成品12(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • Linux groupdel命令详解|用户组删除、主组报错解决、强制删除实战教程
  • 21_LangChain源码总览_读源码前必看的地图
  • 2026年VIVO嵌入式岗位高频面试题(含参考答案)
  • 郴州热门火锅店理性测评|行业避坑+科学选型指南
  • 2026年精选好口碑苦荞粉推荐,健康美味不容错过
  • Codex 编程智能体入门指南
  • 2026封神!5款AI论文平台实测,小白变学霸,初稿直逼优秀模板!
  • 单卡训练大模型:LLaMA Factory显存优化实战
  • 【Crypto】RSA 小指数入门解密
  • Harness 介绍及使用场景
  • GORM 单表操作与高级查询
  • 哪怕MCP再强,我也劝你保留一点“控制欲”