zoukankan      html  css  js  c++  java
  • 利刃 MVVMLight 3:双向数据绑定

          上篇我们已经了解了MVVM的框架结构和运行原理。这里我们来看一下伟大的双向数据绑定。
    说到双向绑定,大家比较熟悉的应该就是AngularJS了,几乎所有的AngularJS 系列教程的开篇几章都要涉及到,真的是很好用。
    表达的效果很简单:就是在界面的操作对数据模型的修改能实时反映到数据;而数据的变更能实时展现到界面。即视图数据模型(ViewModel)和视图(View)之间的双向绑定和触发。
     
     
     
    我们来操作一个试试看:
    第一步:先写一个Model,里面包含我们需要的数据信息,代码如下:
     1     /// <summary>
     2     /// 用户信息
     3     /// </summary>
     4     public class UserInfoModel : ObservableObject
     5     {
     6         private String userName;
     7         /// <summary>
     8         /// 用户名称
     9         /// </summary>
    10         public String UserName
    11         {
    12             get { return userName; }
    13             set { userName = value; RaisePropertyChanged(()=>UserName); }
    14         }
    15 
    16         private Int64 userPhone;
    17         /// <summary>
    18         /// 用户电话
    19         /// </summary>
    20         public Int64 UserPhone
    21         {
    22             get { return userPhone; }
    23             set { userPhone = value; RaisePropertyChanged(() => UserPhone); }
    24         }
    25 
    26         private Int32 userSex;
    27         /// <summary>
    28         /// 用户性别
    29         /// </summary>
    30         public Int32 UserSex
    31         {
    32             get { return userSex; }
    33             set { userSex = value; RaisePropertyChanged(()=>UserSex); }
    34         }
    35 
    36         private String userAdd;
    37         /// <summary>
    38         /// 用户地址
    39         /// </summary>
    40         public String UserAdd
    41         {
    42             get { return userAdd; }
    43             set { userAdd = value; RaisePropertyChanged(() => UserAdd); }
    44         }
    45     }
    第二步:写一个ViewModel,包含了View所需要的命令和属性:
     1     public class BothWayBindViewModel:ViewModelBase
     2     {
     3         public BothWayBindViewModel()
     4         {
     5             UserInfo = new UserInfoModel();
     6         }
     7         
     8         #region 属性
     9 
    10         private UserInfoModel userInfo;
    11         /// <summary>
    12         /// 用户信息
    13         /// </summary>
    14         public UserInfoModel UserInfo
    15         {
    16             get { return userInfo; }
    17             set { userInfo = value; RaisePropertyChanged(() => UserInfo); }
    18         }
    19 
    20         #endregion
    21         
    22         #region 命令
    23         #endregion
    24     }
    第三步:在ViewModelLocator中注册我们写好的ViewModel:SimpleIoc.Default.Register<BothWayBindViewModel>();
     1 /*
     2   In App.xaml:
     3   <Application.Resources>
     4       <vm:ViewModelLocator xmlns:vm="clr-namespace:MVVMLightDemo"
     5                            x:Key="Locator" />
     6   </Application.Resources>
     7   
     8   In the View:
     9   DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
    10 
    11   You can also use Blend to do all this with the tool's support.
    12   See http://www.galasoft.ch/mvvm
    13 */
    14 
    15 using GalaSoft.MvvmLight;
    16 using GalaSoft.MvvmLight.Ioc;
    17 using Microsoft.Practices.ServiceLocation;
    18 
    19 namespace MVVMLightDemo.ViewModel
    20 {
    21     /// <summary>
    22     /// This class contains static references to all the view models in the
    23     /// application and provides an entry point for the bindings.
    24     /// </summary>
    25     public class ViewModelLocator
    26     {
    27         /// <summary>
    28         /// Initializes a new instance of the ViewModelLocator class.
    29         /// </summary>
    30         public ViewModelLocator()
    31         {
    32             ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    33 
    34             #region Code Example
    35             ////if (ViewModelBase.IsInDesignModeStatic)
    36             ////{
    37             ////    // Create design time view services and models
    38             ////    SimpleIoc.Default.Register<IDataService, DesignDataService>();
    39             ////}
    40             ////else
    41             ////{
    42             ////    // Create run time view services and models
    43             ////    SimpleIoc.Default.Register<IDataService, DataService>();
    44             ////}
    45             #endregion
    46 
    47             SimpleIoc.Default.Register<MainViewModel>();
    48             SimpleIoc.Default.Register<WelcomeViewModel>();
    49             SimpleIoc.Default.Register<BothWayBindViewModel>();    
    50         }
    51 
    52         #region 实例化
    53         public MainViewModel Main
    54         {
    55             get
    56             {
    57                 return ServiceLocator.Current.GetInstance<MainViewModel>();
    58             }
    59         }
    60 
    61         public WelcomeViewModel Welcome
    62         {
    63             get
    64             { 
    65                return ServiceLocator.Current.GetInstance<WelcomeViewModel>();
    66             }
    67         }
    68 
    69         public BothWayBindViewModel BothWayBind
    70         {
    71             get
    72             { 
    73                 return ServiceLocator.Current.GetInstance<BothWayBindViewModel>();
    74             }
    75         }     
    76 
    77         #endregion
    78 
    79         public static void Cleanup()
    80         {
    81             // TODO Clear the ViewModels
    82         }
    83     }
    84 }
    第四步:编写View(注意标红的代码):
     
     1 <Window x:Class="MVVMLightDemo.View.BothWayBindView"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         DataContext="{Binding Source={StaticResource Locator},Path=BothWayBind}"
     5         Title="BothWayBindView" Height="300" Width="300">
     6     <Grid>
     7             <StackPanel Orientation="Vertical" Margin="10,10,0,0">
     8                 <StackPanel Orientation="Horizontal" >
     9                     <TextBlock Text="请输入姓名:" ></TextBlock>
    10                     <TextBox Text="{Binding UserInfo.UserName,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Width="200" ></TextBox>
    11                 </StackPanel>
    12 
    13                 <StackPanel Margin="0,10,0,0" Orientation="Horizontal" >
    14                     <TextBlock Text="Hello " ></TextBlock>
    15                     <TextBlock Text="{Binding UserInfo.UserName}" ></TextBlock>
    16                 </StackPanel>
    17 
    18                 <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" >
    19                 </StackPanel>
    20                 
    21             </StackPanel>
    22     </Grid>
    23 </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,当源改变的时候,会通知它进行修改。
     
     
    转载请标明出处,谢谢
     
  • 相关阅读:
    poj 3616 Milking Time
    poj 3176 Cow Bowling
    poj 2229 Sumsets
    poj 2385 Apple Catching
    poj 3280 Cheapest Palindrome
    hdu 1530 Maximum Clique
    hdu 1102 Constructing Roads
    codeforces 592B The Monster and the Squirrel
    CDOJ 1221 Ancient Go
    hdu 1151 Air Raid(二分图最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/wzh2010/p/6286923.html
Copyright © 2011-2022 走看看