欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MVVMLight项目之双向数据绑定

程序员文章站 2022-01-23 10:22:10
目录第一步:先写一个model,里面包含我们需要的数据信息第二步:写一个viewmodel第三步:在viewmodellocator中注册我们写好的viewmodel:第四步:编写view(注意标红的...

mvvm和mvvmlight框架介绍及在项目中的使用详解

mvvmlight项目model view结构及全局视图模型注入器

前篇我们已经了解了mvvm的框架结构和运行原理。这里我们来看一下伟大的双向数据绑定。

说到双向绑定,大家比较熟悉的应该就是angularjs了,几乎所有的angularjs 系列教程的开篇几章都要涉及到,真的是很好用。

表达的效果很简单:就是在界面的操作对数据模型的修改能实时反映到数据;而数据的变更能实时展现到界面。即视图数据模型(viewmodel)和视图(view)之间的双向绑定和触发。

MVVMLight项目之双向数据绑定

我们来操作一个试试看:

第一步:先写一个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的修改,所以下面那行文字也相应改变改变。):

MVVMLight项目之双向数据绑定

前面我们已经了解到了,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项目双向数据绑定的资料请关注其它相关文章!