最近在利用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中的顯示如下:
源碼下載
最后么當然是提供源碼下載了