MVVMLight项目之双向数据绑定
mvvmlight项目model view结构及全局视图模型注入器
前篇我们已经了解了mvvm的框架结构和运行原理。这里我们来看一下伟大的双向数据绑定。
说到双向绑定,大家比较熟悉的应该就是angularjs了,几乎所有的angularjs 系列教程的开篇几章都要涉及到,真的是很好用。
表达的效果很简单:就是在界面的操作对数据模型的修改能实时反映到数据;而数据的变更能实时展现到界面。即视图数据模型(viewmodel)和视图(view)之间的双向绑定和触发。
我们来操作一个试试看:
第一步:先写一个model,里面包含我们需要的数据信息
代码如下:
/// <summary> /// 用户信息 /// </summary> public class userinfomodel : observableobject { private string username; /// <summary> /// 用户名称 /// </summary> public string username { get { return username; } set { username = value; raisepropertychanged(()=>username); } } private int64 userphone; /// <summary> /// 用户电话 /// </summary> public int64 userphone { get { return userphone; } set { userphone = value; raisepropertychanged(() => userphone); } } private int32 usersex; /// <summary> /// 用户性别 /// </summary> public int32 usersex { get { return usersex; } set { usersex = value; raisepropertychanged(()=>usersex); } } private string useradd; /// <summary> /// 用户地址 /// </summary> public string useradd { get { return useradd; } set { useradd = value; raisepropertychanged(() => useradd); } }
第二步:写一个viewmodel
包含了view所需要的命令和属性:
public class bothwaybindviewmodel:viewmodelbase { public bothwaybindviewmodel() { userinfo = new userinfomodel(); } #region 属性 private userinfomodel userinfo; /// <summary> /// 用户信息 /// </summary> public userinfomodel userinfo { get { return userinfo; } set { userinfo = value; raisepropertychanged(() => userinfo); } } #endregion #region 命令 #endregion }
第三步:在viewmodellocator中注册我们写好的viewmodel:
simpleioc.default.register<bothwaybindviewmodel>();
/* in app.xaml: <application.resources> <vm:viewmodellocator xmlns:vm="clr-namespace:mvvmlightdemo" x:key="locator" /> </application.resources> in the view: datacontext="{binding source={staticresource locator}, path=viewmodelname}" you can also use blend to do all this with the tool's support. see http://www.galasoft.ch/mvvm */ using galasoft.mvvmlight; using galasoft.mvvmlight.ioc; using microsoft.practices.servicelocation; namespace mvvmlightdemo.viewmodel { /// <summary> /// this class contains static references to all the view models in the /// application and provides an entry point for the bindings. /// </summary> public class viewmodellocator { /// <summary> /// initializes a new instance of the viewmodellocator class. /// </summary> public viewmodellocator() { servicelocator.setlocatorprovider(() => simpleioc.default); #region code example ////if (viewmodelbase.isindesignmodestatic) ////{ //// // create design time view services and models //// simpleioc.default.register<idataservice, designdataservice>(); ////} ////else ////{ //// // create run time view services and models //// simpleioc.default.register<idataservice, dataservice>(); ////} #endregion simpleioc.default.register<mainviewmodel>(); simpleioc.default.register<welcomeviewmodel>(); simpleioc.default.register<bothwaybindviewmodel>(); } #region 实例化 public mainviewmodel main { get { return servicelocator.current.getinstance<mainviewmodel>(); } } public welcomeviewmodel welcome { get { return servicelocator.current.getinstance<welcomeviewmodel>(); } } public bothwaybindviewmodel bothwaybind { get { return servicelocator.current.getinstance<bothwaybindviewmodel>(); } } #endregion public static void cleanup() { // todo clear the viewmodels } }
第四步:编写view(注意标红的代码)
<window x:class="mvvmlightdemo.view.bothwaybindview" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" datacontext="{binding source={staticresource locator},path=bothwaybind}" title="bothwaybindview" height="300" width="300"> <grid> <stackpanel orientation="vertical" margin="10,10,0,0"> <stackpanel orientation="horizontal" > <textblock text="请输入姓名:" ></textblock> <textbox text="{binding userinfo.username,updatesourcetrigger=propertychanged,mode=twoway}" width="200" ></textbox> </stackpanel> <stackpanel margin="0,10,0,0" orientation="horizontal" > <textblock text="hello " ></textblock> <textblock text="{binding userinfo.username}" ></textblock> </stackpanel> <stackpanel horizontalalignment="center" verticalalignment="center" orientation="horizontal" > </stackpanel> </stackpanel> </grid> </window>
效果如图所示(当修改输入框的内容的时候,对应绑定数据相应改变,并触发对ui的修改,所以下面那行文字也相应改变改变。):
前面我们已经了解到了,raisepropertychanged的作用是当数据源改变的时候,会触发propertychanged事件达到通知ui更改的目的(viewmodel => view)。
那view上的变化要怎么通知到数据源呢:
view中文本框绑定内容如下:
{binding userinfo.username,updatesourcetrigger=propertychanged,mode=twoway},
大家会看到多了两个属性,一个是updatesourcetrigger,一个是mode属性。
updatesourcetrigger的作用是 当做何种改变的时候通知数据源我们做了改变。
枚举类型 | 效果 |
default | 默认值(默认为lostfocuse) |
explicit | 当应用程序调用 updatesource 方法时生效 |
lostfocus | 失去焦点的时候触发 |
propertychanged | 数据属性改变的时候触发 |
这边我们直接使用 propertychanged,当ui数据改变的时候,我们再通知到数据源去做修改。
还有一个属性就是mode,他有五个参数:
枚举类型 | 效果 |
oneway | 源发生变化,数据就会从源流向目标 |
onetime | 绑定会将数据从源发送到目标;但是,仅当启动了应用程序或 datacontext 发生更改时才会如此操作,因此,它不会侦听源中的更改通知。 |
onewaytosource | 绑定会将数据从目标发送到源 |
twoway | 绑定会将源数据发送到目标,但如果目标属性的值发生变化,则会将它们发回给源 |
default | 绑定的模式根据实际情况来定,如果是可编辑的就是twoway,只读的就是oneway |
这边明显有很多种选择,明确一点的是,我们是想把view上的变化同步到viewmodel(target => source),所以使用onewaytosource、twoway、default或者不写都可以。
严谨点应该使用onewaytosource。因为是文本框,属于可以编辑控件,所以 default指向的是twoway。
下面还有一个textblock,仅仅用于显示的,所以不需要目标对源的修改,无需指定就默认是oneway,当源改变的时候,会通知它进行修改。
以上就是mvvmlight项目之双向数据绑定的详细内容,更多关于mvvmlight项目双向数据绑定的资料请关注其它相关文章!
上一篇: C语言数组和指针,内存之间的关系
下一篇: Spring中自定义拦截器的使用
推荐阅读
-
Vue 框架之键盘事件、健值修饰符、双向数据绑定
-
前端笔记之微信小程序(二){{}}插值和MVVM模式&数据双向绑定&指令&API
-
VUE-Table上绑定Input通过render实现双向绑定数据的示例
-
vue数据双向绑定原理解析(get & set)
-
vue.js的双向数据绑定Object.defineProperty方法的神奇之处
-
AngularJS学习笔记(三)数据双向绑定的简单实例
-
vue2.0数据双向绑定与表单bootstrap+vue组件
-
[Asp.net之旅]--数据绑定控件之ListView
-
ListView的Adapter使用(绑定数据) 之 自定义每一项的布局去绑定数据
-
Vue.js 踩坑记之双向绑定