糖果派对官方网站_可以赌钱的糖果游戏_手机版
享用三个WinForm下实现MVVM的大致框架

享用三个WinForm下实现MVVM的大致框架

作者:操作系统    来源:未知    发布时间:2020-01-29 05:54    浏览量:

Web前端本事的大力发展,各类跨平台的依据HTML5的活动前端开垦能力日趋成熟,种种应用稳步由守旧的C/S调换成B/S,APP情势,基于C/S方式的前端技巧譬喻WPF的关怀度渐渐下落,因而WPF上的MVVM并不是利用得很广,近日众多遗留的要么新的C/S系统仍旧使用WinForms技艺开采维护,可是WinForms上却从不精美的MVVM框架,WinForms的UI效果和总体开荒品质,开垦效能未有拿走有效巩固,要过度到WPF开垦这种分裂开荒风格的技艺难度又相当的大,所以,倘若有豆蔻梢头种能够在WinForms上的MVVM框架,无疑是大规模后端.NET程序猿的教义。作者一贯是二个加油在一线的.NET开荒职员,结构师,对于Web和桌面,后端开辟技能都有不认为奇的关联,深入了然开辟人士自嘲本身为“码农”的思想的,专业困苦又从鸡时间陪女朋友陪亲戚,所以本红尘接计算整理怎样提升花销成效,校勘开采品质的主意,经过近10年的时光,发展完美了黄金年代套开辟框架—SOD框架。近年来研商修改Web前端开垦的能力,Vue.js框架的MVVM思想每每次让自个儿认为WinForms上MVVM本领的要求性,开采要促成MVVM框架其实并轻巧,关键在于模型和视图的双向绑定,即模型的变动引起视图内容的改换,而视图的改换也能够唤起模型的转移。SOD框架的实体类能够平素用来作为MVVM上的Model提需求View做为被绑定对象,由此要大家只须求减轻WinForms格局的View成分怎么样兑现绑定操作,那么大家的WinForms应用就可以兑现MVVM功能了。在WinForms上,控件基本上都早就达成了绑定功能,它便是控件的DataBindings,向它助长绑定就能够,比如上面的事例:

火热的MVVM框架

前几日几年最畅销的技术之生机勃勃便是后面三个本领了,各类前端框架,前端标准和前端设计风格不可胜举,而在许多前端框架中具有MVC,MVVM成效的框架成为耀眼新星,比方GitHub关心度相当的高的Vue.js ,由于是同胞文章,其安插风格和文书档案友好度对国人来说更胜一筹,由此笔者也将它推荐到同盟社利用,当中我推荐都理由就是它丰硕雅观的MVVM作用,面向数据并非面向DOM细节相比jQuery等特别节省代码,更合乎后端工程师的胃口,也更有益于UI设计人士跟技术员都分工同盟。

上面是Vue.js完毕MVVM作用的原理图:

                       bb电子糖果派对 1

 

前方说的Vue.js框架那一个亮点的是或不是很眼熟?没有错,那正是明年流行于WPF的MVVM才具,比较WinForms技能,WPF可以提需要UI设计人士更是强有力的统筹力量,做出更炫越来越美观的分界面。只但是MS的多多技术总是很超前技能修改超级快,WPF新坐蓐的时候WinForms还占有桌面开垦重要领域,随后还未有曾火起来活动支付时期已经赶到,基于Web的前端技能大大提升,从而风头盖过了WPF,可是WPF引进的MVVM思想却在Web前端获得了弘扬,今后种种基于MVVM的前端框架犹如雨后春笋。

this.textbox1.DataBindings.Add("Text",userEntity,"Name");

WinForms上的MVVM需求

Web前端技巧的大力发展,各样跨平台的依靠HTML5的移动前端开拓技巧日趋成熟,种种应用稳步由古板的C/S 调换来 B/S ,应用程式方式,基于C/S形式的前端技巧举个例子WPF的关切度渐渐减弱,由此WPF上的MVVM实际不是使用得很广,如今广大余留的或许新的 C/S系统还是接收WinForms工夫开采维护,可是WinForms 上却尚无好好的MVVM框架,WinForms 的UI效果和完整支付品质,开垦成效未有博得平价增进,要过度到WPF开采这种不一样开垦风格的技巧难度又比较大,所以,假如有风流洒脱种能够在 WinForms 上的MVVM框架,无疑是大范围后端.NET技师的佛法。

 

小编一向是三个奋漫不经意在一线的.NET开辟职员,构造师,对于Web 和桌面,后端开垦技能皆有附近的关联,深切明白开拓人士自嘲本人为“码农”的心理的,工作费力又尚龙时间陪女票陪家里人,所以自身间接计算收拾如何狠抓开采作用,改革开采质量的情势,经过近10年的时间,发展完美了意气风发套开拓框架—SOD框架。近日切磋修改Web前端开辟的手艺,Vue.js框架的MVVM观念每每回让自个儿感觉WinForms上MVVM手艺的供给性,开采要完毕MVVM框架其实并轻易,关键在于模型(Model)和视图(View)的双向绑定,即模型的改善引起视图内容的更动,而视图的改变也能够唤起模型的退换。

 

诸有此类当文本框架输入的源委改换后,实体类对象userEntity.Name属性的值也会改换。要是userEntity是SOD实体类,所以userEntity.Name改造,文本框的Text属性也会一齐转移。使用SOD的WinFormsMVVM框架,只须求在codebehind写如下相近的代码:

SOD WinForms MVVM落成原理

要兑现这种转移,对于被绑定方,必需具备属性退换通告成效,当绑定方改换的时候,公告被绑定方让它做相应的管理。在.NET中,实现这种布告作用的接口就是:

 INotifyPropertyChanged

它的定义在System.dll 中,早在 .NET 2.0 就曾经支撑。下边是该接口的切实定义:

namespace System.ComponentModel
{
    // 摘要: 
    //     向客户端发出某一属性值已更改的通知。
    public interface INotifyPropertyChanged
    {
        // 摘要: 
        //     在更改属性值时发生。
        event PropertyChangedEventHandler PropertyChanged;
    }
}

SOD框架的实体类基类 EntityBase 达成了此接口:

public abstract class EntityBase : INotifyPropertyChanged, ICloneable, PWMIS.Common.IEntity
{
/// <summary>
        /// 属性改变事件
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// 触发属性改变事件
        /// </summary>
        /// <param name="propertyFieldName">属性改变事件对象</param>
        protected virtual void OnPropertyChanged(string propertyFieldName)
        {
            if (this.PropertyChanged != null)
            {
                string currPropName = EntityFieldsCache.Item(this.GetType()).GetPropertyName(propertyFieldName);
                this.PropertyChanged(this, new PropertyChangedEventArgs(currPropName));
            }
       }
// 其它代码略… … 
  }

故此SOD框架的实体类能够从来用来作为MVVM上的Model提供给View 做为被绑定对象,因此要大家只需求减轻WinForms 方式的View 成分怎样得以达成绑定操作,那么大家的WinForms 应用就可以兑现MVVM功效了。在WinForms 上,控件基本上都早就完成了绑定功效,它正是控件的 DataBindings,向它助长绑定即可,譬如上面包车型地铁例证:

 

this.textbox1.DataBindings.Add("Text", userEntity, "Name");

那般当文本框架输入的开始和结果改造后,实体类对象 userEntity.Name 属性的值也会改换。就算userEntity是SOD实体类,所以userEntity.Name 更换,文本框的Text属性也会联手转移。

 

SOD框架的数额控件(WinForms,WebForms卡塔尔(قطر‎都落到实处了 IDataControl 接口,它定义了多少个首要的性质 LinkObject,LinkProperty :

/// <summary>
    /// 数据映射控件接口
    /// </summary>
    public interface IDataControl
    {

        /// <summary>
        /// 与数据库数据项相关联的数据
        /// </summary>
        string LinkProperty
        {
            get;
            set;
        }

        /// <summary>
        /// 与数据关联的表名
        /// </summary>
        string LinkObject
        {
            get;
            set;
        }
// 其它接口方法内容略… … 

我们能够利用 LinkObject 来内定要绑定的实体类对象,而LinkProperty 来钦命要绑定的靶子的习性,由此能够经过下边包车型地铁代码达成WinForms 控件与SOD实体类的双向绑定:

 

public void BindDataControls(Control.ControlCollection controls)
        {
            var dataControls = MyWinForm.GetIBControls(controls);
            foreach (IDataControl control in dataControls)
            {
                //control.LinkObject 这里都是 "DataContext"
                object dataSource = GetInstanceByMemberName(control.LinkObject);
                if (control is TextBox)
                {
                    ((TextBox)control).DataBindings.Add("Text", dataSource, control.LinkProperty);
                }
                if (control is Label)
                {
                    ((Label)control).DataBindings.Add("Text", dataSource, control.LinkProperty);
                }
                if (control is ListBox)
                {
                    ((ListBox)control).DataBindings.Add("SelectedValue", dataSource, control.LinkProperty, false, DataSourceUpdateMode.OnPropertyChanged);
                }
            }
        }

 

其它,大家恐怕还亟需将 一些指令绑定到视图上,而要完结此意义也比较简单:

private Dictionary<object, CommandMethod> dictCommand;
public delegate void CommandMethod();

        public void BindCommandControls(Control control,CommandMethod command)
        {
            if (control is Button)
            {
                dictCommand.Add(control, command);
                ((Button)control).Click += (sender, e) => {
                    dictCommand[sender](); 
                };
            }
        }

透过那样的进度后,我们仅须要在窗体加载事件上写下边包车型地铁几行代码就能够了:

SubmitedUsersViewModel DataContext{get;set;}

       private void Form1_Load(object sender, EventArgs e)
        {
            base.BindDataControls(this.Controls);
            base.BindCommandControls(this.button1, DataContext.SubmitCurrentUsers);
            base.BindCommandControls(this.button2, DataContext.UpdateUser);
            base.BindCommandControls(this.button3, DataContext.RemoveUser);
        }

地方的代码中,首先定义了一个视图模型对象 DataContext,在方式BindDataControls 里面作为绑定到视图控件上的对象,它里面包车型大巴CurrentUser属性的Name属性绑定到了文本框控件上,所以 CurrentUser.Name 是作为复合属性来绑定的,对于标签控件和列表框控件,也是相像的历程,如下图:

bb电子糖果派对 2

bb电子糖果派对 3

 

诸如此比,在视图上做轻松的数额属性设置和写少些的code behind绑定代码,二个独具双向绑定功效的次第就好了。

 

SubmitedUsersViewModelDataContext{get;set;}privatevoidForm1_Load(objectsender,EventArgse){base.BindDataControls(this.Controls);base.BindCommandControls(this.button1,DataContext.SubmitCurrentUsers);base.BindCommandControls(this.button2,DataContext.UpdateUser);base.BindCommandControls(this.button3,DataContext.RemoveUser);}

MVVM示例应用方案

详细使用进度,请看此文《“老坛泡新菜”:SODMVVM框架,让WinForms焕发新春》

消除方案大概浏览

为了向大家演示SOD框架对于MVVM的帮衬,大家搭建叁个轻便易行的技术方案,生龙活虎共分为多少个体系程序集,分别对应MVVM的三大学一年级部分:

WinFormMvvm:            WinForm 示例程序主程序,视图类所在程序集

WinFormMvvm.Model:      模型类程序集

WinFormMvvm.ViewModel:  视图模型程序集

bb电子糖果派对 , 

搭建好的消除方案图如下:

bb电子糖果派对 4

 

注意:此设计方案是应用SOD Ver 5.5.5.1019 做的,因为那是当前nuget 上SOD的版本,最新的SOD框架已经把WinFormMvvm项目标 MvvmForm.cs 文件放入到框架之内了。

 程序在App.config中钦点了此番附加测验的数据库,数据库类型为 Access,暗中认可的连天字符串只怕供给Office 二〇〇六上述版本扶植。

下面是App.config 的内容:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name ="default" connectionString ="Provider=Microsoft.ACE.OLEDB.12.0;Jet OLEDB:Engine Type=6;Data Source=testdb.accdb" providerName="Access"/>
  </connectionStrings>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="PWMIS.Core" publicKeyToken="17ba13a12b9fd814" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.5.5.1019" newVersion="5.5.5.1019" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

设若你要求更低版本的 Access 数据库支持,或然换用别的数据库(举个例子SqlServerState of Qatar,请阅读参照他事他说加以考察下边步骤提供的音讯:

1,张开下边链接:

  

2,见到内容章节“3,改进下App.config 文件的三回九转配置”;

3,点击本节下的链接“2.2.3 扩大数据访问类配置”。

 

 

创建MVVM的WinForm视图

那是一个回顾的WinForm 窗体,有三个SOD“数据控件”,包含:二个标签控件展现顾客的ID,文本框控件显示客户名,贰个列表框控件展现已经有顾客列表,多个开关分别用来向列表增添,修改和删除数据。

bb电子糖果派对 5

对此数据控件,能够在那窗体设计器分界面,张开“工具箱”,在“常规”选项卡里面,选用上下文菜单“接纳项”,浏览到packagesPDF.NET.SOD.WinForm.Extensions.5.5.5.1020lib目录,选择“Pwmis.Windows.dll” ,就可以知到SOD的数目控件,然后拖拽到窗体上就能够。

bb电子糖果派对 6

只顾大家不会给这七个按键控件直接设置单击事件,而是经过命令绑定的款型。比方对应加多开关,大家如下绑定命令(视图模型的贰个主意):

base.BindCommandControls(this.button1, DataContext.SubmitCurrentUsers);

那会将助长顾客的开关控件的单击事件,绑定到DataContext的SubmitCurrentUsers 方法上。

 

而对此数据控件的绑定,只必要下边包车型大巴一整套代码:

 

base.BindDataControls(this.Controls);

 

前边早就说过,该方法会遍历方法上首先个参数里面包车型客车富有数据控件,找到LinkObject和LinkProperty属性,达成多少控件和视图模型对象的绑定,这里绑定的是 DataContext对象的CurrentUser对象的习性。

 

单击属性浏览器中多少控件的LinkProperty 属性旁边的“…”开关,会弹出下边包车型客车“数据控件属性选取器”窗体:

bb电子糖果派对 7

 

是因为这里我们要绑定的指标是近期窗体的DataContext对象,所以必要浏览挑选到主程序集,那样在品质名称后生可畏栏,交易会示此目的具备的质量和子属性。注意要是DataContext对象未有出以往列表里面,要求检讨Form 窗体是不是注脚了 DataContext对象,何况需求首先编译叁回程序集。最后,单击鲜明,我们就安装好了数量控件要绑定的音信。

 

创建MVVM的模型

大家的模型很简短,正是担任创立新客商,加载原来就有客商,增加,改革只怕去除顾客,并且这几个操作都以针对数据库的,也等于大家普通的CRUD操作。由于是自己要作为模范遵守规则没有太多逻辑,大家直接看代码就能够:

bb电子糖果派对 8bb电子糖果派对 9

public class UserModel
    {
        private static int index = 0;
        private LocalDbContext context;
        public UserModel()
        {
            context = new LocalDbContext();
        }

        public List<UserEntity> GetAllUsers()
        {
            var list= OQL.From<UserEntity>().ToList(context.CurrentDataBase);
            int max = list.Max(p => p.ID);
            index = ++max;
            return list;
        }
        public void UpdateUser(UserEntity user)
        {
            int count= context.Update<UserEntity>(user);
        }

        public void AddUsers(IList<UserEntity> users)
        {
            int count = context.AddList(users);
        }

        public void SubmitUser(UserEntity user)
        {
           int count = context.Add(user);
        }

        public void RemoveUser(UserEntity user)
        {
            int count = context.Remove(user);
        }

        public UserEntity CreateNewUser(string userName="NoName")
        {
            return new UserEntity()
            {
                 ID= ++index,
                 Name =userName
            };
        }
    }

View Code

客商模型类会使用客户实体类,它也很简短,独有多个ID属性和二个Name属性,详细内容如下:

public class UserEntity:EntityBase
    {
       public UserEntity()
       {
           TableName = "Tb_User";
           PrimaryKeys.Add("UserID");
       }
        public int ID {
            get { return getProperty<int>("UserID"); }
            set { setProperty("UserID", value); }
        }

        public string Name
        {
            get { return getProperty<string>("UserName"); }
            set { setProperty("UserName", value); }
        }

    }

该客户实体类固然很简短,却得以一向提须求视图作为模型绑定的成分,因为SOD实体类都落到实处了“属性校正通告”接口,前边早就详细表明。

接下去正是操作此顾客实体类的多寡上下文了,客户模型类显示了什么样利用它,不过它的定义却很简短:

    class LocalDbContext : DbContext
    {
        public LocalDbContext()
            : base("default")
        {
            //local 是连接字符串名字 
        }

        protected override bool CheckAllTableExists()
        {
            //创建用户表 
            CheckTableExists<UserEntity>();
            return true;
        }
    }

由来,一个总结的MVVM模型类的成套定义就产生了。

 

创设MVVM的视图模型

视图模型是对视图的三个抽象,它包裹了至关心注重要的视图管理逻辑,与MVP的Presenter分裂,视图模型并不会富含详细视图成分的空洞,譬如二个虚无的列表控件,而是对视图大概用到的数码实行李包裹装,何况大概含有对后端MVVM的模子对象调用。

在本例中,大家的客户视图模型的功效也比较轻松,正是提供视图须求的顾客列表和响应视图的加码,矫正,删除客户的授命,详细代码如下

bb电子糖果派对 10bb电子糖果派对 11

public class SubmitedUsersViewModel
    {

        private UserModel model = new UserModel();
        public BindingList<UserEntity> Users { get; private set; }
        public UserEntity CurrentUser { get; private set; }


        UserEntity _selectUser;
        /// <summary>
        /// 当前选择的用户,如果设置,则会设置当前用户
        /// </summary>
        public UserEntity SelectedUser {
            get { return _selectUser; }
            set {
                _selectUser = value;
                this.CurrentUser.ID = value.ID;
                this.CurrentUser.Name = value.Name;
            }

        }

        int _selectedUserID;
        public int SelectedUserID
        {
            get { return _selectedUserID; }
            set {
                _selectedUserID = value;
                var obj = this.Users.FirstOrDefault(p=>p.ID==value);
                if (obj != null)
                {
                    this.CurrentUser.ID = obj.ID;
                    this.CurrentUser.Name = obj.Name;
                    _selectUser = this.CurrentUser;
                }

            }
        }

        public SubmitedUsersViewModel()
        {
            var data = model.GetAllUsers();
            Users = new BindingList<UserEntity>(data);
            CurrentUser = new UserEntity();

        }

        public void UpdateUser()
        {
            var obj = this.Users.FirstOrDefault(p => p.ID == this.CurrentUser.ID);
            if (obj != null)
            {
                obj.Name = this.CurrentUser.Name;
                //更新后必须调用 ResetBindings 方法,否则控件上的数据会丢失一行
                this.Users.ResetBindings();

                model.UpdateUser(obj);
            }

        }
        public void UpdateUser(int id,string name)
        {
            var obj = this.Users.FirstOrDefault(p => p.ID == id);
            if (obj != null)
            {
                obj.Name = name;
                //更新后必须调用 ResetBindings 方法,否则控件上的数据会丢失一行
                this.Users.ResetBindings();

                model.UpdateUser(obj);
            }
        }

        public void SubmitUsers(UserEntity user)
        {
            //UserEntity newUser = new UserEntity();
            //newUser.ID = user.ID;
            //newUser.Name = user.Name;
            //Users.Add(newUser);
            if (!Users.Contains(user))
            {
                Users.Add(user);
                model.SubmitUser(user);            
            }
        }
        public void SubmitCurrentUsers()
        {
            UserEntity newUser = model.CreateNewUser(CurrentUser.Name);
            SubmitUsers(newUser);
            CurrentUser.ID = newUser.ID;
        }

        public void RemoveUser()
        {
            if (SelectedUser == null)
            {

                return;
            }
            var obj = this.Users.FirstOrDefault(p => p.ID == SelectedUser.ID);
            if (obj != null)
            {
                this.Users.Remove(obj);
                //更新后必须调用 ResetBindings 方法,否则控件上的数据会丢失一行
                this.Users.ResetBindings();

                model.RemoveUser(obj);
            }
        }
    }

View Code

友情链接: 网站地图
Copyright © 2015-2019 http://www.tk-web.com. bb电子糖果派对有限公司 版权所有