C# 實踐之 基於winform的mvvm模型,使UI獨立,邏輯可測


背景:在winform中可以使用databinding 達到PM模式的開發,但擴展性與可測試性還是不如WPF那樣完善,我們使用nuget中第三方庫,mvvm fx-winforms,達到數據、業務與UI完全分離開發,並且ui邏輯,業務邏輯完全可測。

 (轉載請注明來源:cnblogs coder-fang)

  1.  使用nuget下載 mvvm fx winforms庫,並引用之。如圖:

 

  3.創建視圖數據模型,代碼如下:

 public class PersonModel:INotifyPropertyChanged
    {
        private string _id;

        public String ID { get { return _id; } set { _id = value; OnPropertyChange("ID"); } }

        private string _name;
        public String Name { get { return _name; } set { _name = value;
            OnPropertyChange("Name"); } }

        private int _sex;
        public int Sex { get { return _sex; } set { _sex = value; OnPropertyChange("Sex"); } }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChange(String prop)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }


    }
View Code

 

 

  4.創建視圖控制器在這里表示為UI邏輯模型,代碼如下:

  public class PersonCtrl
    {
        public MyTab mytab;
        public PersonModel cur_model;
        public List<PersonModel> lstModel = new List<PersonModel>();
        
        public PersonCtrl()
        {

            for (int i = 0; i < 3; i++ )
            {
                lstModel.Add(new PersonModel() { ID = i.ToString(), Name = "test" + i, Sex = i % 2});
            }                

            cur_model = lstModel[0];
        }

        public PersonModel GenCurModel()
        {
            return cur_model;
           
        }
        public void ShowModel(object param=null)
        {
            Console.WriteLine("id:" + cur_model.ID + " name:" + cur_model.Name + " sex:" + cur_model.Sex);
        }

        
    }
View Code

   注:在這里我們暫時只測試cur_model的數據綁定

    5.創建UI業務邏輯的單元測試,代碼如下:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyTabControl;
using MvvmFx.Windows.Data;
using MvvmFx.Windows.Input;
using MvvmFx.Windows;
using MvvmFx.ComponentModel;
using MvvmFx.Windows.Forms;



namespace UnitTes
{

    [TestClass]
    public class UnitTest1
    {
        PersonCtrl ctrl = null;
        BindingManager mgr = null;
        CommandBindingManager cmdMgr = null;
            
        [TestInitialize]
        public void Setup()
        {
            ctrl = new PersonCtrl();
            mgr = new BindingManager();
            cmdMgr = new CommandBindingManager();
        }
        
        [TestMethod]
        public void TestMethod1()
        {
            PersonModel model = new PersonModel() { ID = "", Name = "", Sex = -1 };
            Assert.AreEqual(model.ID, "");
            mgr.Bind(model, "ID").To(ctrl.cur_model, "ID").Activate();
            ctrl.cur_model.ID = "13";
            Assert.AreEqual(model.ID, "13");
            model.ID = "1";
            Assert.AreEqual(ctrl.cur_model.ID, "1");
        }

        [TestMethod]
        public void TestCmd()
        {
            String click = "";
            MvvmFx.Windows.Forms.UserControl btn = new MvvmFx.Windows.Forms.UserControl();
            BoundCommand cmd = new BoundCommand((s) =>
            {
                click = "clicked";
            }, (s) => {
                return ctrl.cur_model.ID.Length > 2;
            }, null);

            cmdMgr.CommandBindings.Add(new CommandBinding(cmd, btn, ControlEvent.Click.ToString()));
                
            Assert.IsFalse(cmd.CanExecute(null));
            ctrl.cur_model.ID = "123";
            Assert.IsTrue(cmd.CanExecute(null));
            cmd.Execute(null);
            Assert.AreEqual(click, "clicked");
        }
    }
}
View Code

  注1:TestMethod1用於測試模型的綁定,cur_model表示數據模型,臨時的model可以表示任意控件,即綁定的兩個值可以互相聯動。

  注2:TestCmd用於測試命令的綁定,且包含了按鈕是否可用的表達示,其中的 MvvmFx.Windows.Forms.UserControl 模擬button控件

 

  6.運行單元測試:

  

   7. 這里只使用了其中比較常用的數據與命令的綁定方式,mvvmfx還有其它很多綁定的方式,大家可以下載代碼查看sample

 


免責聲明!

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



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