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:

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中的顯示如下:

源碼下載

最后么當然是提供源碼下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM