zoukankan      html  css  js  c++  java
  • winform 里使用MVVM模式

    https://www.cnblogs.com/bluedoctor/p/6060278.html

    让WinForms焕发新春 火热的MVVM框架

    MVVM最早是在WPF开发中了解到的,现在流行的web前端框架Vue也借鉴了这种思路:Viewmodel Binder View,我个人的话说就是:视图就是数据,数据就是视图。

     在web端使用Vue.js能很方便使数据与element进行双向绑定,使得前后端的耦合度大大的降低;

    重新回到winform,使用MVVM来做项目,顺便记录下,注意:只是viewModel与view的双向绑定,viewmodel与Model转换自己想方法。

    先来2个Viewmodel,操作重点是Student,继承INotifyPropertyChanged,当ViewModel的属性发生改变,即执行了set访问器时,触发PropertyChanged事件,通知前端      

    public class Room
       {
           public int Id { get; set; }
           string _number;
           string _building;
           int _max;
           public string Number { get; set; }
           public string Building { get; set; }
           public string Address
           {
               get
               {
                   if (Number != null && Building != null)
                   {
                       return Building + Number;
                   }
                   return "";
               }
           }
           public int Max { get; set; }
       }
    public class Student : INotifyPropertyChanged
    {
      
        private string _name = string.Empty;
        private DateTime _brithday = DateTime.Parse("1753-01-01 00:00:00.000");
        private double _high;
        private decimal _money;
        private bool _enable = true;
        private int? _roomId;
        private Room _room;
        private double _qty;
        private decimal _price;
     
        public int Id { get; set; }
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
        public DateTime Brithday
        {
            get
            {
                return _brithday;
            }
            set
            {
                _brithday = value;
                OnPropertyChanged("Brithday");
            }
        }
         
        public double High
        {
            get
            {
                return _high;
            }
            set
            {
                _high = value;
                OnPropertyChanged("High");
            }
        }
        
        public decimal Money
        {
            get
            {
                return _money;
            }
            set
            {
                _money = value;
                OnPropertyChanged("Money");
            }
        }
        
        public bool Enable
        {
            get
            {
                return _enable;
            }
            set
            {
                _enable = value;
                OnPropertyChanged("Enable");
            }
        }
        
        public int? RoomId
        {
            get
            {
                if (Room != null)
                {
                    _roomId = Room.Id;
                }
                return _roomId;
            }
            set { }
        }
     
        public Room Room
        {
            get
            {
                return _room;
            }
            set
            {
                _room = value;
                OnPropertyChanged("Room");
            }
        }
        public double Qty
        {
            get
            {
                return _qty;
            }
            set
            {
                _qty = value;
                OnPropertyChanged("Qty");
                OnPropertyChanged("Account");
            }
        }
      
        public decimal Price
        {
            get
            {
                return _price;
            }
            set
            {
                _price = value;
                OnPropertyChanged("Price");
                OnPropertyChanged("Account");
            }
        }
        public decimal Account
        {
            get
            {
                if (_qty != 0 && _price != 0)
                {
                    var s = decimal.Parse(_qty.ToString()) * _price;
                    return s;
                }
                return 0;
            }
        }
     
     
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string proName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(proName));
        }
    }

    然后是winform界面,要对student对象操作,把这些textbox,checkbox,combobox的tag设置为对应student对象的属性名

     思路:通过找到窗体内所有控件,如果tag属性与studnet的属性相同,则把控件与student对象属性绑定;

    先上后台代码:

    public partial class MVVM : Form
        {
            private Student VModel;
            private List<Room> Rooms = new List<Room>() {
                new Room {Id=0, Building="",Number="请选择..." }
            };
            public MVVM()
            {
                InitializeComponent();
                #region 模拟数据
                VModel = new Student
                {
                    //属性赋值表示以修改模式打开这个页面,如果是新增模式,把属性都注释掉
                    //已测试,修改、新增模式都可通过
                    Id = 1,
                    Name = "Jack",
                    Brithday = DateTime.Now.AddYears(-22),
                    Enable = true,
                    High = 175.4,
                    Money = 10000000000.5m,
                    Room = new Room { Id = 2, Building = "A栋", Number = "102", Max = 8 },
                    RoomId = 2
                };
                if (VModel.Room != null) Rooms.Add(VModel.Room);
                #endregion
            }
            /// <summary>
            /// 递归获取所有控件
            /// </summary>
            /// <param name="ctl"></param>
            /// <returns></returns>
            private List<Control> GetAllControl(Control ctl)
            {
                List<Control> result = new List<Control>();
                if (ctl.HasChildren)
                {
                    if (!(ctl is Form)) result.Add(ctl);
                    foreach (Control item in ctl.Controls)
                    {
                        result.AddRange(GetAllControl(item));
                    }
                }
                else
                {
                    result.Add(ctl);
                }
    
                return result;
            }
            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
    
                this.cbxRoom.DisplayMember = "Address";
                this.cbxRoom.ValueMember = "Id";
    
                this.cbxRoom.DataSource = Rooms;
    
                List<Control> list = GetAllControl(this);
                var propes = VModel.GetType().GetProperties();
                try
                {
                    foreach (Control item in list)
                    {
                        var prop = propes.FirstOrDefault(a => item.Tag != null && a.Name == item.Tag.ToString());
                        if (prop != null)
                        {
                            if (item is TextBox) item.DataBindings.Add(new Binding("Text", VModel, prop.Name));
                            if (item is CheckBox) item.DataBindings.Add(new Binding("Checked", VModel, prop.Name));
                            if (item is ComboBox) item.DataBindings.Add(new Binding("SelectedItem", VModel, prop.Name));
    
                        }
                    }
                }
                catch (Exception)
                {
    
                    throw;
                }
            }
    
          /// <summary>
          /// 查看 button
          /// </summary>
          /// <param name="sender"></param>
          /// <param name="e"></param>
            private void button1_Click(object sender, EventArgs e)
            {
                MessageBox.Show(Newtonsoft.Json.JsonConvert.SerializeObject(VModel));
            }
            /// <summary>
            /// 更改属性 button
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void button2_Click(object sender, EventArgs e)
            {
                #region 测试更改viewmodel属性,视图是否会更新
                VModel.Name = "Bob";
                Room r6 = Rooms.FirstOrDefault(a => a.Id == 6);
                if (r6 != null) VModel.Room = r6;
                VModel.Qty = 120;
                VModel.Price = 12;
                #endregion
            }
            /// <summary>
            /// 标识是否已从服务器获取到数据
            /// </summary>
            private bool IsLoadRooms = false;
            /// <summary>
            /// room combobox DropDown事件处理,第一次从服务器获取数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void cbxRoom_DropDown(object sender, EventArgs e)
            {
                if (!IsLoadRooms)
                {
                    #region 模拟请求服务器得到数据
                    for (int i = 0; i < 10; i++)
                    {
                        Room r = new Room { Building = "A栋", Max = 8, Number = "10" + (i + 1), Id = i + 1 };
                        if (!Rooms.Exists(a => a.Id == r.Id))
                        {
                            Rooms.Add(r);
                        }
                    }
                    #endregion
                    //重新绑定数据源
                    this.cbxRoom.DataSource = null;
                    this.cbxRoom.DisplayMember = "Address";
                    this.cbxRoom.ValueMember = "Id";
                    this.cbxRoom.DataSource = Rooms;
                    IsLoadRooms = true;
    
                }
            }
        }

    说明:

    1、GetAllControl 方法获取所有控件,toolstrip里 的toolstripButton是不能获取到的,还有其他的一些控件,这里不谈论;

    2、当前页面是进行对象进行新增、修改、参看等操作的页面

    3、VModel的Room属性类型为其他对象,需要对其进行操作时,第一次从服务器端请求数据源,保存到当前的Rooms List里;

    4、不同控件绑定的属性是不同的,如name属性类型为string,可用放到textbox里绑定,即textbox.text=name,同理,checkbox绑定checked 对象类型为bool,combobox是数据源选择,默认给一个提示选择item,然后让他绑定数据源rooms,新增操作时,vmodel.Room是null,所有当前combobox.selecteditem还是默认第一个;以修改模式打开时vmodel.Room有值时,经过binding后,selecteditem就是当前vmodel.Room,当然前提是把Room属性值放到rooms中;

    现在运行试试

     效果还不错,对了,binding还有一个好处就是可用验证输入数据合理性

    ( ̄▽ ̄)"

     

     

  • 相关阅读:
    silverlight 视频
    Win7/Vista下安装SQL Server 2005/2008后,进行附加数据库错误的解决
    IIS篇
    ARCGIS 定位篇
    sqlserver 2008 修改表结构不能保存
    更新silverlight 后 无法启动调试 未安装silverlight developer 运行时解决办法
    2点经纬度计算相对方位
    VS2010中文旗舰版在WIN7 64位操作系统下安装
    self = [super init]
    NSXMLParser XML 解析 解压
  • 原文地址:https://www.cnblogs.com/Smina/p/14036805.html
Copyright © 2011-2022 走看看