MVVMLight項目之雙向數(shù)據(jù)綁定
MVVMLight項目Model View結(jié)構(gòu)及全局視圖模型注入器
前篇我們已經(jīng)了解了MVVM的框架結(jié)構(gòu)和運行原理。這里我們來看一下偉大的雙向數(shù)據(jù)綁定。
說到雙向綁定,大家比較熟悉的應該就是AngularJS了,幾乎所有的AngularJS 系列教程的開篇幾章都要涉及到,真的是很好用。
表達的效果很簡單:就是在界面的操作對數(shù)據(jù)模型的修改能實時反映到數(shù)據(jù);而數(shù)據(jù)的變更能實時展現(xiàn)到界面。即視圖數(shù)據(jù)模型(ViewModel)和視圖(View)之間的雙向綁定和觸發(fā)。

我們來操作一個試試看:
第一步:先寫一個Model,里面包含我們需要的數(shù)據(jù)信息
代碼如下:
/// <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>效果如圖所示(當修改輸入框的內(nèi)容的時候,對應綁定數(shù)據(jù)相應改變,并觸發(fā)對UI的修改,所以下面那行文字也相應改變改變。):

前面我們已經(jīng)了解到了,RaisePropertyChanged的作用是當數(shù)據(jù)源改變的時候,會觸發(fā)PropertyChanged事件達到通知UI更改的目的(ViewModel => View)。
那View上的變化要怎么通知到數(shù)據(jù)源呢:
View中文本框綁定內(nèi)容如下:
{Binding UserInfo.UserName,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay},
大家會看到多了兩個屬性,一個是UpdateSourceTrigger,一個是Mode屬性。
UpdateSourceTrigger的作用是 當做何種改變的時候通知數(shù)據(jù)源我們做了改變。
| 枚舉類型 | 效果 |
| Default | 默認值(默認為LostFocuse) |
| Explicit | 當應用程序調(diào)用 UpdateSource 方法時生效 |
| LostFocus | 失去焦點的時候觸發(fā) |
| PropertyChanged | 數(shù)據(jù)屬性改變的時候觸發(fā) |
這邊我們直接使用 PropertyChanged,當UI數(shù)據(jù)改變的時候,我們再通知到數(shù)據(jù)源去做修改。
還有一個屬性就是Mode,他有五個參數(shù):
| 枚舉類型 | 效果 |
| OneWay | 源發(fā)生變化,數(shù)據(jù)就會從源流向目標 |
| OneTime | 綁定會將數(shù)據(jù)從源發(fā)送到目標;但是,僅當啟動了應用程序或 DataContext 發(fā)生更改時才會如此操作,因此,它不會偵聽源中的更改通知。 |
| OneWayToSource | 綁定會將數(shù)據(jù)從目標發(fā)送到源 |
| TwoWay | 綁定會將源數(shù)據(jù)發(fā)送到目標,但如果目標屬性的值發(fā)生變化,則會將它們發(fā)回給源 |
| Default | 綁定的模式根據(jù)實際情況來定,如果是可編輯的就是TwoWay,只讀的就是OneWay |
這邊明顯有很多種選擇,明確一點的是,我們是想把View上的變化同步到ViewModel(Target => Source),所以使用OneWayToSource、TwoWay、Default或者不寫都可以。
嚴謹點應該使用OneWayToSource。因為是文本框,屬于可以編輯控件,所以 Default指向的是TwoWay。
下面還有一個TextBlock,僅僅用于顯示的,所以不需要目標對源的修改,無需指定就默認是OneWay,當源改變的時候,會通知它進行修改。
以上就是MVVMLight項目之雙向數(shù)據(jù)綁定的詳細內(nèi)容,更多關(guān)于MVVMLight項目雙向數(shù)據(jù)綁定的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android ViewPager無限循環(huán)滑動并可自動滾動完整實例
對于Android ViewPager廣告頁可無限循環(huán)滑動并可自動滾動帶有小圓點的這個功能很多APP都有這個功能,這里為大家提供了完整的實例代碼2018-03-03

