網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
MVVM和MVVMLight框架介紹及在項(xiàng)目中的使用詳解
MVVMLight項(xiàng)目Model?View結(jié)構(gòu)及全局視圖模型注入器
前篇我們已經(jīng)了解了MVVM的框架結(jié)構(gòu)和運(yùn)行原理。這里我們來(lái)看一下偉大的雙向數(shù)據(jù)綁定。
說(shuō)到雙向綁定,大家比較熟悉的應(yīng)該就是AngularJS了,幾乎所有的AngularJS 系列教程的開(kāi)篇幾章都要涉及到,真的是很好用。
表達(dá)的效果很簡(jiǎn)單:就是在界面的操作對(duì)數(shù)據(jù)模型的修改能實(shí)時(shí)反映到數(shù)據(jù);而數(shù)據(jù)的變更能實(shí)時(shí)展現(xiàn)到界面。即視圖數(shù)據(jù)模型(ViewModel)和視圖(View)之間的雙向綁定和觸發(fā)。
我們來(lái)操作一個(gè)試試看:
第一步:先寫(xiě)一個(gè)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); } }
第二步:寫(xiě)一個(gè)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中注冊(cè)我們寫(xiě)好的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 實(shí)例化 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 } }
第四步:編寫(xiě)View(注意標(biāo)紅的代碼)
<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="請(qǐng)輸入姓名:" ></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>
效果如圖所示(當(dāng)修改輸入框的內(nèi)容的時(shí)候,對(duì)應(yīng)綁定數(shù)據(jù)相應(yīng)改變,并觸發(fā)對(duì)UI的修改,所以下面那行文字也相應(yīng)改變改變。):
前面我們已經(jīng)了解到了,RaisePropertyChanged的作用是當(dāng)數(shù)據(jù)源改變的時(shí)候,會(huì)觸發(fā)PropertyChanged事件達(dá)到通知UI更改的目的(ViewModel => View)。
那View上的變化要怎么通知到數(shù)據(jù)源呢:
View中文本框綁定內(nèi)容如下:
{Binding UserInfo.UserName,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay},
大家會(huì)看到多了兩個(gè)屬性,一個(gè)是UpdateSourceTrigger,一個(gè)是Mode屬性。
UpdateSourceTrigger的作用是 當(dāng)做何種改變的時(shí)候通知數(shù)據(jù)源我們做了改變。
枚舉類型 | 效果 |
Default | 默認(rèn)值(默認(rèn)為L(zhǎng)ostFocuse) |
Explicit | 當(dāng)應(yīng)用程序調(diào)用 UpdateSource 方法時(shí)生效 |
LostFocus | 失去焦點(diǎn)的時(shí)候觸發(fā) |
PropertyChanged | 數(shù)據(jù)屬性改變的時(shí)候觸發(fā) |
這邊我們直接使用 PropertyChanged,當(dāng)UI數(shù)據(jù)改變的時(shí)候,我們?cè)偻ㄖ綌?shù)據(jù)源去做修改。
還有一個(gè)屬性就是Mode,他有五個(gè)參數(shù):
枚舉類型 | 效果 |
OneWay | 源發(fā)生變化,數(shù)據(jù)就會(huì)從源流向目標(biāo) |
OneTime | 綁定會(huì)將數(shù)據(jù)從源發(fā)送到目標(biāo);但是,僅當(dāng)啟動(dòng)了應(yīng)用程序或 DataContext 發(fā)生更改時(shí)才會(huì)如此操作,因此,它不會(huì)偵聽(tīng)源中的更改通知。 |
OneWayToSource | 綁定會(huì)將數(shù)據(jù)從目標(biāo)發(fā)送到源 |
TwoWay | 綁定會(huì)將源數(shù)據(jù)發(fā)送到目標(biāo),但如果目標(biāo)屬性的值發(fā)生變化,則會(huì)將它們發(fā)回給源 |
Default | 綁定的模式根據(jù)實(shí)際情況來(lái)定,如果是可編輯的就是TwoWay,只讀的就是OneWay |
這邊明顯有很多種選擇,明確一點(diǎn)的是,我們是想把View上的變化同步到ViewModel(Target => Source),所以使用OneWayToSource、TwoWay、Default或者不寫(xiě)都可以。
嚴(yán)謹(jǐn)點(diǎn)應(yīng)該使用OneWayToSource。因?yàn)槭俏谋究颍瑢儆诳梢跃庉嬁丶?Default指向的是TwoWay。
下面還有一個(gè)TextBlock,僅僅用于顯示的,所以不需要目標(biāo)對(duì)源的修改,無(wú)需指定就默認(rèn)是OneWay,當(dāng)源改變的時(shí)候,會(huì)通知它進(jìn)行修改。
原文鏈接:https://www.cnblogs.com/wzh2010/p/6286923.html
相關(guān)推薦
- 2022-03-26 c#使用listbox的詳細(xì)方法和常見(jiàn)問(wèn)題解決_C#教程
- 2022-07-01 tensorflow可視化Keras框架中Tensorboard使用示例_python
- 2021-12-07 C語(yǔ)言實(shí)現(xiàn)頁(yè)面置換算法(FIFO、LRU)_C 語(yǔ)言
- 2023-07-06 css flex實(shí)現(xiàn)div固定在瀏覽器右下角
- 2022-11-17 Android形狀圖形與狀態(tài)列表圖形及九宮格圖片超詳細(xì)講解_Android
- 2022-11-21 Python?Flask框架開(kāi)發(fā)之運(yùn)用SocketIO實(shí)現(xiàn)WebSSH方法詳解_python
- 2022-06-02 Python?推導(dǎo)式、生成器與切片問(wèn)題解決思路_python
- 2022-11-10 Android?Jetpack組件支持庫(kù)DataBinding與ViewModel與LiveData
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支