MVC in WinForm

最近在利用C# WinForm进行项目编码的时候发现,如果不恰当的使用Partial关键字或者是User Control,会导致逻辑代码和UI代码耦合度过高,往往会造成一个页面下面会有将近2000行代码……这,当然不是我所要看到的,我急需要一种模式能够将代码分散,并且最好做到逻辑和UI的分离。找来找去,发现MVC模式最好用,就用这个吧。

当然,拿来用,肯定得明白它的实现方式,对于MVC这种模式,我也已经不是第一次接触了,就来简单的说点吧。

MVC基本概念

MVC,指的是Model View Controller,其核心是利用Controller来策动Model和View,简而言之,Controller就是生成Model和View的。请看下面的图示:

这里我就来说下创建步骤:

首先,Controller中需要有待操作的View和与之对应的Model,然后主要进行逻辑代码的编写。

其次,View中需要有之对应的Controller的实例,这样才能方便调用Controller中的逻辑方法。

最后就是启动的时候,最好是Controller First,而不是View First.

需要注意的是,在MVC中,我们倾向于在Model类中使用INtofifyPropertyChanged接口;我们倾向于利用DataBindings来绑定数据。

MVC具体使用实例

下面就以一个刚刚编写的字模制作小软件来说明:

在Controller中,我们需要指明需要操作的View和Model:

public WordMakerController(MainFrm mainFrm)
{
this.mainFrm = mainFrm;
this.mainFrm.MController = this;

//调用构造器实现数据缓存
wordReponsitory = new WordReponsitory();
}

//我要操作的View
public MainFrm mainFrm;

//我要操作的Model
public object datasource = DataCache.model;

指明之后,剩下的就是操作逻辑了:

//添加操作,主要是将标记写入
public void Add(Button thisBtn, string flag)
{

thisBtn.Text = flag;
string content = string.Empty;
if (flag.Contains("/"))
content = @"strArray[" + thisBtn.Tag + "]=" + "\"/\";";
if (flag.Contains("\\"))
content = @"strArray[" + thisBtn.Tag + "]=" + "@" + "\"\\\";";

if (!list.Contains(content))
{
list.Add(content);
SortAndIntegration();
}
}

//删除操作,删除已有的标记。
public void Remove(Button thisBtn, string flag)
{
string content = string.Empty;
if (flag.Contains("/"))
content = @"strArray[" + thisBtn.Tag + "]=" + "\"/\";";
if (flag.Contains("\\"))
content = @"strArray[" + thisBtn.Tag + "]=" + "@" + "\"\\\";";

thisBtn.Text = string.Empty;
if (list.Contains(content))
{
list.Remove(content);
SortAndIntegration();
}
}

//对List数组进行排序
private void SortAndIntegration()
{
list.Sort(1, list.Count - 1, null);
DataCache.model.MyArray = string.Join(newLine, list.ToArray());
}

//本字模软件的核心就是此类,将输入的字母拷贝到一个大数组,然后循环行列打印出来。
private void Punch(int count, string[,] strDaemon, string[,] strPartly)
{
for (int row = 0; row < 7; row++)
{
for (int column = 0; column < 16; column++)
{
strDaemon[row, count * 16 + column] = strPartly[row, column];
}
}
}

//解析输入的单词
public string[,] make(string text)
{
//string text = txtWord.Text;

int len = text.Length;

string[,] str = new string[7, len * 16];
int count = -1;
foreach (char c in text)
{
switch (c)
{
case ‘A‘:
count++;
Punch(count, str, WordReponsitory.strArrayA);
break;

case ‘B‘:
count++;
Punch(count, str, WordReponsitory.strArrayB);
break;

case ‘C‘:
count++;
Punch(count, str, WordReponsitory.strArrayC);
break;

case ‘D‘:
count++;
Punch(count, str, WordReponsitory.strArrayD);
break;

case ‘E‘:
count++;
Punch(count, str, WordReponsitory.strArrayE);
break;

case ‘F‘:
count++;
Punch(count, str, WordReponsitory.strArrayF);
break;

case ‘G‘:
count++;
Punch(count, str, WordReponsitory.strArrayG);
break;

case ‘H‘:
count++;
Punch(count, str, WordReponsitory.strArrayH);
break;

case ‘I‘:
count++;
Punch(count, str, WordReponsitory.strArrayI);
break;

case ‘J‘:
count++;
Punch(count, str, WordReponsitory.strArrayJ);
break;

case ‘K‘:
count++;
Punch(count, str, WordReponsitory.strArrayK);
break;

case ‘L‘:
count++;
Punch(count, str, WordReponsitory.strArrayL);
break;

case ‘T‘:
count++;
Punch(count, str, WordReponsitory.strArrayT);
break;

case ‘O‘:
count++;
Punch(count, str, WordReponsitory.strArrayO);
break;
default: break;

}
}
return str;
}

在Model中,倾向于利用INotifyPropertyChanged接口实现属性改变后通知到绑定

public class NotifiedModel:INotifyPropertyChanged
{

private string myArray;
public string MyArray
{
get { return myArray; }
set { myArray = value; NotifyPropertyChanged("MyArray"); }
}

public event PropertyChangedEventHandler PropertyChanged;

public void NotifyPropertyChanged(string info)
{
PropertyChangedEventHandler property_changed = PropertyChanged;
if (property_changed != null)
{
property_changed(this,new PropertyChangedEventArgs(info));
}
}
}

在View中,需要实例化Controller,然后调用Controller代码逻辑即可,所有的操作基本都和UI交互有关,大大降低了代码的耦合度:

public MainFrm()
{
InitializeComponent();
}

//这里需要保存Controller的实例,以便方便调用逻辑方法
private WordMakerController mController;
public WordMakerController MController
{
get { return mController; }
set { mController = value; }
}

private void MainFrm_Load(object sender, EventArgs e)
{
//这里是进行数据绑定
string header = "string[,] strArray = new string[7, 16];";
mController.list.Add(header);
richTextBox1.DataBindings.Add("Text", mController.datasource, "MyArray");

LoadWordModel();
}

private void LoadWordModel()
{
Button[,] btn = new Button[7, 16];

for (int m = 0; m < 7; m++)
{
for (int n = 0; n < 16; n++)
{
btn[m, n] = new Button();
Button t = btn[m, n];

t.Size = new Size(20, 20);
t.FlatStyle = FlatStyle.Popup;
t.Top = m * 20;
t.Left = n * 20;
t.Tag = m + "," + n;

t.MouseDown += (senderE, eE) =>
{
ClickAndFlag(senderE, eE);
};

panel1.Controls.Add(t);
}
}
}

//这里通过点击鼠标,然后将标记加入到数组里。主要进行字模制作
private void ClickAndFlag(object senderE, object eE)
{
Button thisBtn = ((Button)(senderE));
if (eE is MouseEventArgs)
{
MouseEventArgs e = eE as MouseEventArgs;
if (e.Button == MouseButtons.Left)
{
if (String.IsNullOrEmpty(thisBtn.Text))
//Add(thisBtn, "\"/\";");
mController.Add(thisBtn, "/;");
else
mController.Remove(thisBtn, "/;");
}
if (e.Button == MouseButtons.Right)
{
if (String.IsNullOrEmpty(thisBtn.Text))
//Add(thisBtn, "@"+"\"\\\";");
mController.Add(thisBtn, "\\;");
else
mController.Remove(thisBtn, "\\;");
}
}
}

//生成字模
private void button1_Click(object sender, EventArgs e)
{
string[,] str = mController.make(txtWord.Text);

string text = txtWord.Text;

int len = text.Length;

for (int row = 0; row < 7; row++)
{
int count = 0;
for (int colum = 0; colum < len * 16; colum++)
{
count++;
//if (string.IsNullOrEmpty(strArrayA[row, colum])) strArrayA[row, colum] = " ";
if (str[row, colum] == null) str[row, colum] = " ";

rText.AppendText(str[row, colum]);

if (count == len * 16)
{
rText.AppendText("\r\n");
}
}
}
}

最后说明下启动,由于是Controller是策动者,所以应当是ControllerFirst:

 //Controller实例化先
            WordMakerController wordMakerController = new WordMakerController(new MainFrm());
            //启动由Controller生成的窗体
            Application.Run(wordMakerController.mainFrm);

实例运行的结果

然后把生成好的字符拷贝到VisualStudio中, 在VisualStudio中的显示如下:

源码下载

最后么当然是提供源码下载

时间: 2024-12-12 09:34:22

MVC in WinForm的相关文章

【WEB API项目实战干货系列】- API访问客户端(WebApiClient适用于MVC/WebForms/WinForm)(四)

这几天没更新主要是因为没有一款合适的后端框架来支持我们的Web API项目Demo, 所以耽误了几天, 目前最新的代码已经通过Sqlite + NHibernate + Autofac满足了我们基本的Demo需求. 按照既定的要求,我们的API会提供给众多的客户端使用, 这些客户端可以是各种Web站点, APP, 或者是WinForm, WPF, Silverlight等诸如此类的应用,将来还有可能是各种Iot等物联网设备的应用,Restful API凭借其诸多优势,已经在移动互联网的时代火了一

二十八、带给我们一种新的编码思路——EFW框架CS系统开发中的MVC模式探讨

回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://pan.baidu.com/s/1eQCc69G       前言:记得最初写出Winform版MVC的代码是在公司的一个产品中,产品有几个界面功能比较多,一个界面窗体的代码尽然有1万多行代码,让我们在维护这几个界面的时候非常的痛苦,你可能想可以把这个大的界面拆分成几个小的界面在集成在一起不就好了,但实际上这样

【WEB API项目实战干货系列】- 导航篇(十足干货分享)

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在今天移动互联网的时代,作为攻城师的我们,谁不想着只写一套API就可以让我们的Web, Android APP, IOS APP, iPad APP, Hybired APP, H5 Web共用共同的逻辑呢? [WEB API项目实战干货系列]

API访问客户端

API访问客户端(WebApiClient适用于MVC/WebForms/WinForm) 这几天没更新主要是因为没有一款合适的后端框架来支持我们的Web API项目Demo, 所以耽误了几天, 目前最新的代码已经通过Sqlite + NHibernate + Autofac满足了我们基本的Demo需求. 按照既定的要求,我们的API会提供给众多的客户端使用, 这些客户端可以是各种Web站点, APP, 或者是WinForm, WPF, Silverlight等诸如此类的应用,将来还有可能是各种

异步编程 In .NET

概述 在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们会做一个async和await在WinForm中的尝试,并且对比在4.5之前的异步编程模式APM/EAP和async/await的区别,最后我们还会探讨在不同线程之间交互的问题. IIS存在着处理能力的问题,但是WinForm却是UI响应的问题,并且WinForm的UI线程至始至终都是同一个,所以两

Farseer.net轻量级开源框架 V1.x 入门篇:数据库配置及其它配置文件

导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 V1.x 入门篇:新版本说明 下一篇:Farseer.net轻量级开源框架 V1.x 入门篇:表实体类映射 前言 Farseer.Net是支持多数据库的ORM,使用者通过配置文件即可切换指定的数据库而不需要修改项目中的任何代码.本篇讲述如何进行数据库环境的配置.同时也讲述其它配置文件的使用. 配置文件 1.配置文件的路径: 不管是WebForm.Mvc.WinForm,配置文件统一放在:~

Log4Net问题和思考

问题 一.日志存储方式 1.txt 2.SQLServer数据库 3.log文件 二.项目类型不同 1winFrom 2webFrom 3MVC 4WPF 5控制台 三.切分依据不同 1.空间大小 2.时间 四.常用属性 文件切分依据(日期.大小 ).存储方式:log.SQLServer  http://www.cnblogs.com/yonghuacui/p/6179196.html 各种数据库  http://zhoufoxcn.blog.51cto.com/792419/429988 WP

异步编程 In .NET(转)

转自:http://www.cnblogs.com/jesse2013/p/Asynchronous-Programming-In-DotNet.html 概述 在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们会做一个async和await在WinForm中的尝试,并且对比在4.5之前的异步编程模式APM/EAP和async/await的区别,最后我们

异步编程 In .NET(转载)

在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们会做一个async和await在WinForm中的尝试,并且对比在4.5之前的异步编程模式APM/EAP和async/await的区别,最后我们还会探讨在不同线程之间交互的问题. IIS存在着处理能力的问题,但是WinForm却是UI响应的问题,并且WinForm的UI线程至始至终都是同一个,所以两者之间