首页 > 代码库 > C# 实践之 基于winform的mvvm模型,使UI独立,逻辑可测

C# 实践之 基于winform的mvvm模型,使UI独立,逻辑可测

背景:在winform中可以使用databinding 达到PM模式的开发,但扩展性与可测试性还是不如WPF那样完善,我们使用nuget中第三方库,mvvm fx-winforms,达到数据、业务与UI完全分离开发,并且ui逻辑,业务逻辑完全可测。

 

  1.  使用nuget下载 mvvm fx winforms库,并引用之。如图:
  2. 技术分享

 

  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。

 

C# 实践之 基于winform的mvvm模型,使UI独立,逻辑可测