您好,欢迎访问一九零五行业门户网

什么是MVVM架构和数据绑定?

(申明:最近在做一个练习,写点东西,谨供参考。)
1、界面展示:其中的布局和样式就不说了,重点在mvvm架构和数据绑定(model层使用ef(entity framework)实体框架,不做介绍)。
绑定后:
2、架构介绍:
在views层中新建cusgroupeditwindow窗体,viewmodels中建立cusgroupeditviewmodel类,在窗体的xaml或者cs中引用viewmodels对应类:
   xaml中:
c879f5c3c9893e45ba2ce7d26e997114   
      92c72cd9b9c57deded9b4898c5a2dbe2 1da84c50fa7328704b2ce9dda53aedda     
    7473f81b006ddc8e53f2d378bc7dce62
cs:datacontext = cusgroupeditviewmodel。(添加引用路径)
/***********************************************/
*csgroup是在viewmodel中定义的一个cusgroup对象,  *
*cusgroup对象是在sql数据库中的表,在ef中的对象。*
/***********************************************/
3、textbox绑定:
ff1681ddee25e4aeb6879b3c67fb00b5
4、button绑定:
5d362da14155c388b940c2445466edf6         
            29deedf2cd939b8bccbf37085c6a617a8b6de9c7d98b148f30b5dd6899a18be9
      a1cb88e6789f399807801ea3799938af 
dfca9557cc388af630eeba6df35e96f8
c05eec64ed02ad0975536668a09b61b7
5、checkbox绑定:
04efaf97de328fe03fc57ff1cb705f93
456c2222d60e5b20af2a55c567b254f7 6、combobox绑定:
6、combobox绑定:
<combobox maxwidth="150" width="100" selectedvalue="{binding strcmbselectvalue, mode=twoway, updatesourcetrigger=propertychanged}" displaymemberpath="text" selectedvaluepath="value" itemssource="{binding lstcsgdownlevelid, mode=twoway,updatesourcetrigger=propertychanged}" />
<!--selectedvalue:选中commobox的值,mode双向模式,属性改变时触发;displaymemberpath:显示时绑定;selectedvaluepath:表示选择下拉框某一项对应的值;itemssource:绑定的数据源 -->
<!-- 其中value和text也可理解为数据源,在viewmodel中有赋值-->
7、datagrid绑定:
<datagrid columnwidth="*" selecteditem="{binding currentselectitem}" itemssource="{binding csgroupsall}" autogeneratecolumns="false" isreadonly="true" > <datagrid.columns> <datagridtextcolumn header="分组编号" binding="{binding code}" /> <datagridtextcolumn header="分组名称" binding="{binding name}" /> </datagrid.columns> </datagrid>
/***************************************************************/
//datagrid当前选择对象private cusgroup currentselectitem;public cusgroup currentselectitem {get { return currentselectitem; }set{ currentselectitem = value; getcutcmbselect(value); } }
view code
<!--代码没有自动缩进,有点不知所措-->
/***************************************************************/
viewmodel 中的代码:
using heyin.erp.datamodels;using heyin.erp.iservices;using heyin.erp.models;using heyin.erp.services;using microsoft.practices.prism.commands;using system;using system.collections.generic;using system.collections.objectmodel;using system.windows;using system.text.regularexpressions;using system.windows.controls;namespace heyin.erp.client.viewmodels.customer {class cusgroupeditviewmodel : baseviewmodel {private bool bisadd = false; icusgroupservice cgs; //调用iservice接口#region properties 属性private guid gcsgroupid = guid.empty;//all cusgroupprivate list<cusgroup> csgroupsall;public list<cusgroup> csgroupsall {get { return csgroupsall; }set{ csgroupsall = value; //设定值onpropertychanged("csgroupsall"); //在属性更改后,通知 } }private list<cusgroup> csgroupsminprestore;public list<cusgroup> csgroupsallminprestore {get { return csgroupsminprestore; }set{ csgroupsminprestore = value; //设定值onpropertychanged("csgroupsallminprestore"); //在属性更改后,通知 } }//cusgroup对象private cusgroup csgroup;public cusgroup csgroup {get { return csgroup; }set{ csgroup = value; onpropertychanged("csgroup"); } }/// <summary>/// /// </summary>private string strcmbselectvalue;public string strcmbselectvalue {get { return strcmbselectvalue; }set{if (value != null) { strcmbselectvalue = value; onpropertychanged("strcmbselectvalue"); } } }/// <summary>/// comboboxdatamodel:作为一个combobox的对象,可以理解为数据源/// </summary>private observablecollection<comboboxdatamodel> lstcsgdownlevelid;public observablecollection<comboboxdatamodel> lstcsgdownlevelid {get { return lstcsgdownlevelid; }set{ lstcsgdownlevelid = value; onpropertychanged("lstcsgdownlevelid"); } }//datagrid当前选择对象private cusgroup currentselectitem;public cusgroup currentselectitem {get { return currentselectitem; }set{ currentselectitem = value; getcutcmbselect(value); } }private int errorcount;public int errorcount { get => errorcount; set => errorcount = value; }#endregion#region commandspublic delegatecommand<string> btnchangedcommand { get; set; }public delegatecommand<cusgroup> txtchangedcommand { get; set; } #endregionpublic cusgroupeditviewmodel() { cgs = new cusgroupservice(); csgroupsall = new list<cusgroup>(); csgroup = new cusgroup(); lstcsgdownlevelid = new observablecollection<comboboxdatamodel>(); btnchangedcommand = new delegatecommand<string>(menuclick); txtchangedcommand = new delegatecommand<cusgroup>(changecmbvalue); getallcusgroups(); }#region buttonclickprivate void menuclick(string strmessage) {if (string.isnullorempty(strmessage)) return;if (csgroup == null) return;switch (strmessage) {case "btncusgroupsave": save();break;case "btncusgroupadd": add();break;case "btncusgroupdelete": delete();break; } }#endregion buttonclick#region motheds/// <summary>/// 获取全部group/// </summary>private void getallcusgroups() {//获取满足条件的客户分组信息 csgroupsall.clear(); csgroupsall = cgs.get(s => s.isdelete == 0); getallcmbitems();//给降档分组下拉框赋值if ((gcsgroupid == null || gcsgroupid == guid.empty) && csgroupsall.count > 0) csgroup = csgroupsall[0]; //给基础信息等赋值strcmbselectvalue = csgroup.downlevelid.tostring();//设置降档分组默认值 }/// <summary>/// 添加/// </summary>/// <param name="cg"></param>private void addcusgroup(cusgroup cg) { cg.id = guid.newguid(); //新建分组guidcg.isdelete = 0; //默认为0:不删除cg.createby = app.getcurrentuserid();//创建人员关联员工 guidcg.createtime = datetime.now; //初始化创建时间,应该使用服务器当前时间bool c = cgs.add(cg);if (c) { messagebox.show(string.format("创建新组别【{0}】成功!", csgroup.name), "提示", messageboxbutton.ok, messageboximage.information); getallcusgroups(); bisadd = false; } }/// <summary>/// 修改/// </summary>/// <param name="cg"></param>private void updatecusgroup(cusgroup cg) { bisadd = false; cg.updatetime = datetime.now; cg.updateby = app.getcurrentuserid();//更新人员关联员工 guidstring[] str = { "updatetime", "updateby" };bool b = cgs.edit(cg, str);if (b) { messagebox.show("更改组别【成功】!", "提示", messageboxbutton.ok, messageboximage.information); getallcusgroups(); } }/// <summary>///删除方法(实为更新)/// </summary>/// <param name="cg"></param>private void deletecusgroup(cusgroup cg) { cg.isdelete = 1; //更改数据库删除标志cg.updatetime = datetime.now; //更新删除时间cg.updateby = app.getcurrentuserid();//更新人员关联员工 guidstring[] str = { "updatetime", "isdelete", "updateby" };bool b = cgs.edit(cg, str);if (b) {//messagebox.show(string.format("已删除组别【{0}】!", csgroup.name), "提示", messageboxbutton.ok, messageboximage.information); getallcusgroups(); csgroup = new cusgroup(); //清空对象bisadd = true; } }/// <summary>/// 插入和更新方法调用/// </summary>private void save() {if (errorcount > 0) {//判断必填数据是否为空:为空则提示messagebox.show("请核对所填数据", "提示", messageboxbutton.yesno, messageboximage.information);return; }if (bisadd) addcusgroup(csgroup);elseupdatecusgroup(csgroup); }/// <summary>/// 获取降档分组下拉列表的值,并指定默认值/// </summary>/// <param name="value"></param>private void getcutcmbselect(cusgroup value) { bisadd = false;//点击新增后,再选择列表的逻辑if (value != null) { csgroup = cgs.getbyid(value.id);//查找出当前选中的对象gcsgroupid = csgroup.id; //保存当前选择对象的guidif (csgroup != null) {if (csgroup.downlevelid.hasvalue) {//如果降档id有值,则默认显示,如果没有,则显示为空getexceptcmbselect();//刷新下拉列表,先刷新,再赋值给默认值strcmbselectvalue = csgroup.downlevelid.tostring(); }else{ lstcsgdownlevelid.clear(); strcmbselectvalue = string.empty; } } } }private void add() { bisadd = true;//点击新建分组时,重新获取所有降档id对应的中文名 getallcmbitems(); csgroup = new cusgroup(); }private void delete() {if (this.csgroup.id == guid.empty || csgroup.id == null) messagebox.show("请选择要删除组别", "提示", messageboxbutton.ok, messageboximage.information);else{ messageboxresult msgresult = messagebox.show(string.format("确定要删除分组【{0}】吗?", csgroup.name), "提示", messageboxbutton.yesno, messageboximage.information);if (msgresult == messageboxresult.yes) deletecusgroup(csgroup); } }/// <summary>/// 排除当前列的降档id和对应的name/// </summary>private void getexceptcmbselect() { lstcsgdownlevelid.clear(); csgroupsallminprestore = cgs.get(s => s.isdelete == 0 && s.minprestore <= csgroup.minprestore);foreach (var idlid in csgroupsallminprestore) {if (idlid.id != csgroup.id) //去除当前选择id对应的namelstcsgdownlevelid.add(new comboboxdatamodel() { value = idlid.id.tostring(), text = idlid.name }); } }/// <summary>/// 获取列表中所有降档id和对应的name/// </summary>private void getallcmbitems() { lstcsgdownlevelid.clear();foreach (var idlid in csgroupsall) { lstcsgdownlevelid.add(new comboboxdatamodel() { value = idlid.id.tostring(), text = idlid.name }); } }private void changecmbvalue(cusgroup cgminprestore) { lstcsgdownlevelid.clear(); list<cusgroup> lsttextchange = new list<cusgroup>(); lsttextchange = cgs.get(s => s.minprestore < cgminprestore.minprestore);foreach (var idlid in lsttextchange) { lstcsgdownlevelid.add(new comboboxdatamodel() { value = idlid.id.tostring(), text = idlid.name }); } }public void sizechangedcommand(object obj, sizechangedeventargs e) { messagebox.show("日了狗"); }#endregion} }
view中代码:
<client:basewindow x:class="heyin.erp.client.views.customer.cusgroupeditwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:interaction="http://schemas.microsoft.com/expression/2010/interactions" xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:commonvalidation="clr-namespace:heyin.erp.common.validation;assembly=heyin.erp.common" xmlns:client="clr-namespace:heyin.erp.client" mc:ignorable="d" x:name="cusgroupwindow" title="客户分组" height="500" width="800" windowstartuplocation="centerowner" loaded="window_loaded" maxboxenable="true" minboxenable="false" > <interactivity:interaction.triggers> <interactivity:eventtrigger eventname="sizechanged"> <interaction:callmethodaction targetobject="{binding}" methodname="sizechangedcommand"/> </interactivity:eventtrigger> </interactivity:interaction.triggers> <grid> <grid.rowdefinitions> <rowdefinition height="*" /> <rowdefinition height="50" /> </grid.rowdefinitions> <grid grid.row="0"> <grid.columndefinitions> <columndefinition width="1*"/> <columndefinition width="2*"/> </grid.columndefinitions> <!-- left --> <grid margin="5,0,5,5"> <groupbox name="gbgroupdata"> <groupbox.headertemplate> <datatemplate> <wrappanel margin="{staticresource wrappanelmarginforinfo}"> <textblock text="客户分组" height="20" /> <button width="20" height="20" margin="50,0,0,0" command="{binding datacontext.btnchangedcommand,relativesource={relativesource mode=findancestor,ancestortype=groupbox}}" commandparameter="btncusgroupadd" visibility="{binding savevisibility,mode=twoway,updatesourcetrigger=propertychanged}"> <image source="..\..\resources\images\16\add.png" /> </button> <button width="20" height="20" margin="10,0,0,0" command="{binding datacontext.btnchangedcommand,relativesource={relativesource mode=findancestor,ancestortype=groupbox}}" commandparameter="btncusgroupdelete" visibility="{binding savevisibility,mode=twoway,updatesourcetrigger=propertychanged}"> <image source="..\..\resources\images\16\clear.png" /> </button> </wrappanel> </datatemplate> </groupbox.headertemplate> <grid> <grid grid.row="1"> <datagrid columnwidth="*" selecteditem="{binding currentselectitem}" itemssource="{binding csgroupsall}" autogeneratecolumns="false" isreadonly="true" > <datagrid.columns> <datagridtextcolumn header="分组编号" binding="{binding code}" /> <datagridtextcolumn header="分组名称" binding="{binding name}" /> </datagrid.columns> </datagrid> </grid> </grid> </groupbox> </grid> <!-- right --> <grid grid.column="1" margin="5"> <grid.rowdefinitions> <rowdefinition height="*"/> <rowdefinition height="100"/> <rowdefinition height="130"/> </grid.rowdefinitions> <!-- 基础信息 --> <grid> <groupbox> <groupbox.header> <textblock text="基础信息" height="20"/> </groupbox.header> <stackpanel> <grid margin="0,10"> <grid.columndefinitions> <columndefinition width="*" /> <columndefinition width="*" /> </grid.columndefinitions> <textbox visibility="collapsed" x:name="tberrorcount" text="{binding errorcount, mode=twoway,updatesourcetrigger=propertychanged}"></textbox> <wrappanel margin="{staticresource wrappanelmarginforinfo}"> <textblock width="60" margin="{staticresource textblockmarginformostleft}"><run text="分组编号" /></textblock> <textbox name="txtcusgropcrod" maxwidth="150" width="100" tooltip="{binding relativesource={relativesource self},path=(validation.errors).currentitem.errorcontent}" validation.error="validation_error"> <textbox.text> <binding path="csgroup.code" mode="twoway" updatesourcetrigger="propertychanged" validatesondataerrors="true" notifyonvalidationerror="true"> <binding.validationrules> <exceptionvalidationrule></exceptionvalidationrule> <commonvalidation:requiredvalidationrule maxlenth="15" errormessage="分组编号" isrequired="true" validatesontargetupdated="true" /> </binding.validationrules> </binding> </textbox.text> </textbox> </wrappanel> <wrappanel margin="{staticresource wrappanelmarginforinfo}" grid.column="1"> <textblock text="分组名称" width="60" margin="{staticresource textblockmarginformostleft}"/> <textbox name="txtcusgropname" maxwidth="150" width="100" tooltip="{binding relativesource={relativesource self},path=(validation.errors).currentitem.errorcontent}" validation.error="validation_error"> <textbox.text> <binding path="csgroup.name" mode="twoway" updatesourcetrigger="propertychanged" validatesondataerrors="true" notifyonvalidationerror="true"> <binding.validationrules> <exceptionvalidationrule></exceptionvalidationrule> <commonvalidation:requiredvalidationrule maxlenth="15" errormessage="分组名称" isrequired="true" validatesontargetupdated="true" /> </binding.validationrules> </binding> </textbox.text> </textbox> </wrappanel> </grid> <grid> <wrappanel margin="{staticresource wrappanelmarginforinfo}"> <textblock margin="{staticresource textblockmarginformostleft}" width="60" verticalalignment="center"><run text="分组描述" /></textblock> <textbox x:name="tbremark" textwrapping="wrap" acceptsreturn="true" verticalscrollbarvisibility="visible" width="400" height="90" tooltip="{binding relativesource={relativesource self},path=(validation.errors).currentitem.errorcontent}" validation.error="validation_error"> <textbox.text> <binding path="csgroup.description" mode="twoway" updatesourcetrigger="propertychanged" validatesondataerrors="true" notifyonvalidationerror="true"> <binding.validationrules> <exceptionvalidationrule></exceptionvalidationrule> <commonvalidation:requiredvalidationrule maxlenth="300" errormessage="分组描述" validatesontargetupdated="true" /> </binding.validationrules> </binding> </textbox.text> </textbox> </wrappanel> </grid> </stackpanel> </groupbox> </grid> <!-- 消费相关 --> <grid grid.row="1" margin="0,10,0,10"> <grid> <groupbox> <groupbox.header> <textblock text="消费相关"/> </groupbox.header> <grid margin="0,10"> <grid.columndefinitions> <columndefinition width="*"/> <columndefinition width="*"/> </grid.columndefinitions> <wrappanel margin="{staticresource wrappanelmarginforinfo}"> <textblock text="消费积分" width="60" height="20" margin="{staticresource textblockmarginformostleft}" /> <textbox name="txtcusgropjf" maxwidth="150" width="100" text="{binding csgroup.pointconversion, mode=twoway,updatesourcetrigger=propertychanged}" /> </wrappanel> <wrappanel grid.column="1" margin="{staticresource wrappanelmarginforinfo}" horizontalalignment="left" verticalalignment="center"> <checkbox name="cbcash" margin="0,0,5,0" ischecked="{binding csgroup.iscash}"/> <textblock text="开通预存或储值时禁止现金交易" /> </wrappanel> </grid> </groupbox> </grid> </grid> <!-- 预存相关 --> <grid grid.row="2"> <groupbox> <groupbox.header> <textblock text="预存相关"/> </groupbox.header> <stackpanel> <grid margin="0,10"> <grid.columndefinitions> <columndefinition width="*"/> <columndefinition width="*"/> </grid.columndefinitions> <wrappanel margin="{staticresource wrappanelmarginforinfo}"> <textblock width="80" margin="{staticresource textblockmarginformostleft}" ><run text="预存最低充值"/></textblock> <textbox maxwidth="150" width="100" text="{binding csgroup.minprestore, mode=twoway,updatesourcetrigger=propertychanged}" /> </wrappanel> <wrappanel grid.column="1" margin="{staticresource wrappanelmarginforinfo}"> <textblock width="80" text="金额低缺报警" margin="{staticresource textblockmarginformostleft}" /> <textbox maxwidth="550" width="100" text="{binding csgroup.alarm,mode=twoway}" /> </wrappanel> </grid> <grid margin="0,5"> <wrappanel margin="{staticresource wrappanelmarginforinfo}"> <textblock width="190" text="预存金额未达到最低要求时降档至" margin="{staticresource textblockmarginformostleft}"/> <combobox maxwidth="150" width="100" selectedvalue="{binding strcmbselectvalue, mode=twoway, updatesourcetrigger=propertychanged}" displaymemberpath="text" selectedvaluepath="value" itemssource="{binding lstcsgdownlevelid, mode=twoway,updatesourcetrigger=propertychanged}" /> </wrappanel> </grid> </stackpanel> </groupbox> </grid> </grid> </grid> <!-- bottom --> <grid grid.row="2"> <wrappanel horizontalalignment="center" verticalalignment="center" margin="{staticresource wrappanelmarginforinfo}"> <button margin="1" command="{binding btnchangedcommand}" commandparameter="btncusgroupsave" background="#fc8530" style="{staticresource savebuttonstyle}" visibility="{binding savevisibility,mode=twoway,updatesourcetrigger=propertychanged}" > <textblock text="保存" fontweight="bold" fontsize="16"></textblock> </button> </wrappanel> </grid> </grid> </client:basewindow>
以上就是什么是mvvm架构和数据绑定?的详细内容。
其它类似信息

推荐信息