MVC in WinForm
发布日期:2021-05-14 04:38:00 浏览次数:15 分类:博客文章

本文共 9500 字,大约阅读时间需要 31 分钟。

最近在利用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:

View Code
public WordMakerController(MainFrm mainFrm)        {            this.mainFrm = mainFrm;            this.mainFrm.MController = this;            //调用构造器实现数据缓存            wordReponsitory = new WordReponsitory();        }        //我要操作的View        public MainFrm mainFrm;        //我要操作的Model        public object datasource = DataCache.model;

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

View Code
//添加操作,主要是将标记写入        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接口实现属性改变后通知到绑定

View Code
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交互有关,大大降低了代码的耦合度:

View Code
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:

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

 实例运行的结果

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

源码下载

最后么当然是提供了

 

上一篇:Unity浅析
下一篇:在net.tcp模式下,由SvcUtil.exe生成代理类文件和配置文件

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月08日 17时57分05秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章