一、概述
本文與其說是MVVMLight框架的學習,不如說是溫故一下數據的雙向綁定。
二、Demo
建立好MVVMLight框架后的Wpf工程后,建立一個Model。Model、View以及ViewModel的代碼如下:
1 using GalaSoft.MvvmLight; 2 3 namespace MvvmLightDemo1.Model 4 { 5 public class WelcomeModel : ObservableObject 6 { 7 private string welcomeMsg; 8 public string WelcomeMsg 9 { 10 get { return welcomeMsg; } 11 set { welcomeMsg = value; RaisePropertyChanged(() => WelcomeMsg); } 12 } 13 } 14 15 }
1 using GalaSoft.MvvmLight; 2 using MvvmLightDemo1.Model; 3 4 namespace MvvmLightDemo1.ViewModel 5 { 6 public class MainViewModel : ViewModelBase 7 { 8 private WelcomeModel welcomeModel; 9 public WelcomeModel WelcomeModel 10 { 11 get { return welcomeModel; } 12 set { welcomeModel = value; RaisePropertyChanged(() => WelcomeModel); } 13 } 14 /// <summary> 15 /// Initializes a new instance of the MainViewModel class. 16 /// </summary> 17 public MainViewModel() 18 { 19 WelcomeModel = new WelcomeModel() { WelcomeMsg = "Welcome to MVVMLight World!" }; 20 } 21 } 22 }
1 using CommonServiceLocator; 2 using GalaSoft.MvvmLight.Ioc; 3 4 namespace MvvmLightDemo1.ViewModel 5 { 6 /// <summary> 7 /// This class contains static references to all the view models in the 8 /// application and provides an entry point for the bindings. 9 /// </summary> 10 public class ViewModelLocator 11 { 12 /// <summary> 13 /// Initializes a new instance of the ViewModelLocator class. 14 /// </summary> 15 public ViewModelLocator() 16 { 17 ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 18 SimpleIoc.Default.Register<MainViewModel>(); 19 } 20 21 public MainViewModel Main 22 { 23 get 24 { 25 return ServiceLocator.Current.GetInstance<MainViewModel>(); 26 } 27 } 28 29 public static void Cleanup() 30 { 31 // TODO Clear the ViewModels 32 } 33 } 34 }
1 <Window x:Class="MvvmLightDemo1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:MvvmLightDemo1" 7 mc:Ignorable="d" 8 Title="MVVMLIghtDemo1" Height="350" Width="525" Background="#FF699DC1"> 9 <Window.DataContext> 10 <Binding Path="Main" Source="{StaticResource Locator}"></Binding> 11 </Window.DataContext> 12 <Grid> 13 <StackPanel > 14 <TextBlock Text="{Binding WelcomeModel.WelcomeMsg}" FontSize="28" Foreground="#FFBB4913" HorizontalAlignment="Center"/> 15 <StackPanel Orientation="Horizontal"> 16 <Label Content="修改信息:" VerticalContentAlignment="Center" FontSize="20" Foreground="#FFC55D21"></Label> 17 <TextBox Text="{Binding Path=WelcomeModel.WelcomeMsg,Mode=TwoWay}" FontSize="20" Foreground="#FFBB4913"/> 18 <Button Content="LostFocus" Background="#FF22A658"></Button> 19 </StackPanel> 20 21 </StackPanel> 22 <StackPanel VerticalAlignment="Top" HorizontalAlignment="Center" > 23 24 </StackPanel> 25 </Grid> 26 </Window>
在View中,我們分別讓一個TextBox和一個TextBlock綁定WelcomeModel中的WelcomeMsg屬性
當我們在TextBox中輸入文本的時候,利用雙向綁定更新WelcomeModel中的WelcomeMsg屬性,WelcomeMsg屬性又通過RaisePropertyChanged來激發屬性變更的事件,通知UI,如此一來,界面上的TextBlock中的內容就會更新。
但是,當我們運行以上程序的時候,修改TextBox里的內容,TextBlock中的內容並沒有實時更新,而是需要按鍵盤上的Tab鍵或者點擊LostFocus按鈕,讓TextBox失去焦點。
這就引出了一個問題,當目標更新的時候,數據源是否更新以及更新的時機?
為了解決這個問題,我們可以使用Binding的UpdateSourceTrigger和Mode屬性
UpdateSourceTrigger屬性的作用:當做何種改變的時候通知數據源我們做了改變,默認值是LostFocus,這就解釋了為什么我們上述程序需要TextBox失去焦點的時候,TextBlock的內容才會更新。
UpdateSourceTrigger可以取以下值:
| 枚舉類型 | 說明 |
| Default | 默認值(默認LostFocus) |
| Explicit | 當應用程序調用 UpdateSource 方法時生效 |
| LostFocus | 失去焦點的時候觸發 |
| PropertyChanged | 屬性改變時立即觸發 |
為了讓TextBlock中的內容隨着TextBox的內容實時變化,我們可以將綁定修改成如下格式:
<TextBox Text="{Binding Path=WelcomeModel.WelcomeMsg,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="20" Foreground="#FFBB4913"/>
Mode屬性取值如下:

通過以上Demo,我們應達成以下共識:
1)ViewModel => View更新的時候,我們一般在屬性的set塊中加入RaisePropertyChanged,它的作用是當數據源改變的時候,會觸發PropertyChanged事件,通知UI屬性發生了變更;
2)View => ViewModel 更新的時候,我們一般利用Binding的UpdateSourceTrigger和Mode屬性。
