雙向數據綁定

 上篇咱們已經瞭解了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的修改,因此下面那行文字也相應改變改變。):app

 
前面咱們已經瞭解到了,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,當源改變的時候,會通知它進行修改。
相關文章
相關標籤/搜索