日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

什么是MVVM模式

發(fā)布時(shí)間:2023/12/31 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 什么是MVVM模式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

問題引入
1?場(chǎng)景一:團(tuán)隊(duì)辛辛苦苦完成了一個(gè)項(xiàng)目,抱著激動(dòng)的心情去給用戶做demo,而用戶給你的反饋是UI很不滿意,要重新修改,否則拒絕驗(yàn)收。大規(guī)模修改UI,晴天霹靂!
2?場(chǎng)景二:產(chǎn)品在一家客戶上線運(yùn)行反應(yīng)不錯(cuò),公司準(zhǔn)備擴(kuò)大營(yíng)銷市場(chǎng),尋求更多的客戶,此時(shí),不同客戶對(duì)UI紛紛提出修改意見,眾口難調(diào),但是老總發(fā)話,客戶是上帝!
問題出來了,按照傳統(tǒng)的開發(fā)模式是基于CodeBehind這樣的方式,UI總是和業(yè)務(wù)邏輯緊密耦合在一起,?UI修改,無(wú)法避免的業(yè)務(wù)邏輯修改隨之而來,這無(wú)非就是我們老生常談的解耦問題,有沒有辦法做到UI層剝離出邏輯層呢?MVVM模式為你排憂解難。

一?什么是MVVM模式
MVVM(Model-View-ViewModel)是專為WPF和SilverLight設(shè)計(jì)的開發(fā)模式,?與之類似的有Asp.net程序?qū)?yīng)的MVC模式,?WinForm程序?qū)?yīng)的MVP,?關(guān)于MVC,?MVP此處不展開論述,詳情參考http://msdn.microsoft.com/zh-cn/library/dd381412(v=vs.98).aspx。?但在MVC和MVP模式中,?View層都具有很多代碼邏輯,?最簡(jiǎn)單的例子是在MVC中當(dāng)界面發(fā)生交互時(shí)View去調(diào)用Controler中的某個(gè)方法,所以?并沒有真正意義上實(shí)現(xiàn)View與ViewModel完全分離。
WPF真正引人入勝、使之與WinForm涇渭分明的特點(diǎn)就是——“數(shù)據(jù)驅(qū)動(dòng)界面”,何為“數(shù)據(jù)驅(qū)動(dòng)界面”?,?與傳統(tǒng)的“事件驅(qū)動(dòng)見面”相比較,數(shù)據(jù)編程了核心,UI處于從屬地位;數(shù)據(jù)是底層、是心臟,數(shù)據(jù)變了作為表層的UI就會(huì)跟著變、將數(shù)據(jù)展現(xiàn)給用戶;如果用戶修改了UI元素上的值,相當(dāng)于透過UI元素直接修改了底層的數(shù)據(jù);圍繞著這個(gè)核心,WPF準(zhǔn)備了很多概念相當(dāng)前衛(wèi)的技術(shù),其中包括為界面準(zhǔn)備的XAML、為底層數(shù)據(jù)準(zhǔn)備的Dependency?Property?&?Binding和為消息傳遞準(zhǔn)備的Routed?Event?&?Command。?
Binding和Command技術(shù)的出現(xiàn),也為MVVM模式成為WPF平臺(tái)下一個(gè)優(yōu)秀的開發(fā)模式奠定了基礎(chǔ)。通過Binding,可以綁定一個(gè)View的Property到ViewModel,?ViewModel?對(duì)象被設(shè)置為視圖的?DataContex,如果屬性值在?ViewModel?更改,這些新值自動(dòng)傳播到通過數(shù)據(jù)綁定的視圖,實(shí)現(xiàn)在ViewModel里可以不通過編寫任何邏輯代碼就直接更新View,做到View與ViewModel之間的完全松耦合,關(guān)于Binding,想了解更多可參見?Data?and?WPF:?Customize?Data?Display?with?Data?Binding?and?WPF?"。?同樣,如果沒有WPF中的Command,?MVVM也很難展示出它的強(qiáng)大力量,ViewModel可將Command暴露給View,?使得View可以消費(fèi)command中對(duì)應(yīng)的邏輯功能,對(duì)于不熟悉command的朋友,可以參考這篇文章Advanced?WPF:?Understanding?Routed?Events?and?Commands?in?WPF。
下面簡(jiǎn)要介紹一下MVVM每個(gè)模塊的主要職責(zé)
1) View主要用于界面呈現(xiàn),與用戶輸入設(shè)備進(jìn)行交互,在code-Behind中還可以些一些UI的邏輯的,比如一些豐富的動(dòng)畫效果,或者直接設(shè)置某個(gè)元素的樣式等,此外,設(shè)置View層的DataContext為對(duì)于的ViewModel層的邏輯也是寫在code-Behind中。
2) ViewModel是MVVM架構(gòu)中最重要的部分,ViewModel中包含屬性,命令,方法,事件,屬性驗(yàn)證等邏輯,用于邏輯實(shí)現(xiàn),負(fù)責(zé)View與Model之間的通信。
3) Model就是我們常說的數(shù)據(jù)模型,用于數(shù)據(jù)的構(gòu)造,數(shù)據(jù)驅(qū)動(dòng),?主要提供基礎(chǔ)實(shí)體的屬性以及每個(gè)屬性的驗(yàn)證邏輯。
MVVM中各個(gè)模塊的交互方式如圖所示:
?

二?為什么要使用MVVM模式
MVVM模式的引入能給我們帶來什么優(yōu)勢(shì)呢?相信這是大多數(shù)學(xué)習(xí)MVVM的人關(guān)心的一個(gè)主要問題。
首先我們應(yīng)該清楚地認(rèn)識(shí)到,MVVM不是適用于任何的項(xiàng)目開發(fā),一個(gè)項(xiàng)目是否要上一套框架取決于項(xiàng)目本身的規(guī)模和性質(zhì),盲目的使用開發(fā)模式可能會(huì)引起過度開發(fā),通常情況下,企業(yè)級(jí)的WPF應(yīng)用軟件建議使用,主要優(yōu)勢(shì)下面將展開詳細(xì)闡述。
1團(tuán)隊(duì)層面?統(tǒng)一了項(xiàng)目團(tuán)隊(duì)的思維方式,也改變了開發(fā)方式,由于View與ViewModel之間的松耦合關(guān)系,我們可以輕易做到開發(fā)團(tuán)隊(duì)與設(shè)計(jì)團(tuán)隊(duì)的明確分工,開發(fā)團(tuán)隊(duì)可以專注于創(chuàng)建功能強(qiáng)大的?ViewModel?類,而設(shè)計(jì)團(tuán)隊(duì)能夠熟練運(yùn)用Blend等工具能為程序員輸出用戶友好的試圖View的XAML文件。而且,隨著項(xiàng)目的進(jìn)行,不斷會(huì)有新的成員加入,一個(gè)清晰的項(xiàng)目設(shè)計(jì)模式,能夠很大程度地減少他熟悉項(xiàng)目的所需時(shí)間,并能夠規(guī)范的進(jìn)行接下來的開發(fā)維護(hù)工作。
2?架構(gòu)層面?項(xiàng)目架構(gòu)更加穩(wěn)定,模塊之間松散的耦合關(guān)系使得模塊之間的相互依賴性大大降低,這也就意味著項(xiàng)目的擴(kuò)展性得到了提高,即使以后需要加一些新的模塊,或者實(shí)現(xiàn)模塊的注入,我們也能做到最小的改動(dòng),從而保證項(xiàng)目的穩(wěn)定。
3?代碼層面MVVM的引入也使得項(xiàng)目本身變得模塊清晰化,條理化,有助于我們更好地區(qū)分哪些邏輯是屬于UI操作,哪些邏輯是業(yè)務(wù)操作,增強(qiáng)了代碼的可讀性、可測(cè)性。對(duì)于ViewModel層,Views和Unit?tests是兩個(gè)不同類型的消費(fèi)者,應(yīng)用程序中的主要交互邏輯處于ViewModel層,這樣,在完成ViewModel之后,我們完全可以有理由相信,我們可以對(duì)ViewModel進(jìn)行單元測(cè)試,因?yàn)樗灰蕾囉谌魏蜺I控件,從這個(gè)角度看,似乎UnitTest相比于View而言具備更大的消費(fèi)能力。

三?詳解ViewModel
 ViewModel是MVVM架構(gòu)中最重要的部分,負(fù)責(zé)View與Model直接的通信,對(duì)于ViewModel的理解是掌握MVVM的關(guān)鍵,下面我們針對(duì)ViewModel進(jìn)行詳細(xì)剖析。?
1?ViewModel的屬性ViewModel的屬性是View數(shù)據(jù)的來源,但ViewModel層不能是Model層的簡(jiǎn)單封裝,ViewModel層也不能是View層的簡(jiǎn)單映射。ViewModel的屬性可由三部分組成:一部分是Model的復(fù)制屬性;另一部分用于控制UI狀態(tài)。例如Button屬性的Disable屬性,當(dāng)操作完成時(shí)可以通過這個(gè)屬性更改通知View做相應(yīng)的UI變換或者后面提到的事件通知;第三部分是一些方法的參數(shù),可以將這些方法的參數(shù)設(shè)置成相應(yīng)的屬性綁定到View中的某個(gè)控件,然后在執(zhí)行方法的時(shí)候獲取這些屬性,所以一般方法不含參數(shù)。
2?ViewModel的命令?ViewModel中的命令用于接受View的用戶輸入,并做相應(yīng)的處理。我們也可以通過方法實(shí)現(xiàn)相同的功能。
3?ViewModel的事件??ViewModel中的事件主要用來通知View做相應(yīng)的UI變換。它一般在一個(gè)處理完成之后觸發(fā),隨后需要View做出相應(yīng)的非業(yè)務(wù)的操作。所以一般ViewModel中的事件的訂閱者只是View,除非其他自定義的非View類之間的交互。
4?View及ViewModel交互模式
在View與ViewModel模型之間進(jìn)行雙向的聯(lián)系的主要方式是通過數(shù)據(jù)綁定。當(dāng)正確地使用該設(shè)計(jì)模式后,每一個(gè)View除了純凈的XAML和非常少量的后置代碼外不會(huì)再包含任何東西,徹底地做到了界面展示和業(yè)務(wù)邏輯的分離,讓程序員更加專注于代碼的編寫。
ViewModel也能用來容納View的狀態(tài)以及執(zhí)行View需要的任何命令。
因?yàn)閃PF內(nèi)置了Command模式,對(duì)于像Button控件之類的UI元素來說都有一個(gè)Command的屬性,它是WPF所定義的ICommand類型。可以把這些命令放到ViewModel中并以公有屬性的形式暴露出來,這樣就可以讓View對(duì)其進(jìn)行綁定。這極其強(qiáng)大,因?yàn)樗梢园袽odelView中的可執(zhí)行代碼綁定到窗體的Button上。

四?MVVM實(shí)踐
理論知識(shí)已經(jīng)準(zhǔn)備充分,現(xiàn)在是檢驗(yàn)真理的時(shí)刻,以下是使用了Model-View-ViewModel?設(shè)計(jì)模式的s世上最簡(jiǎn)單的WPF應(yīng)用程序例子,簡(jiǎn)單加法計(jì)算器。
1?代碼結(jié)構(gòu)如下圖:
?

2?CaculatorModel類:
public?class?CaculatorModel
????{
????????public?int?Num1?{?get;?set;?}
????????public?int?Num2?{?get;?set;?}
????????public?int?Result?{?get;?set;?}
}

3?ICommand類型的基類DelegateCommand

using?System;
using?System.Windows.Input;
namespace?MVVMDemo.Commands
{
????public?class?DelegateCommand:ICommand
????{
????????public?DelegateCommand(Action<object>?executeCommand,?Func<object,?bool>?canExecuteCommand)
????????{
????????????this.executeCommand?=?executeCommand;
????????????this.canExecuteCommand?=?canExecuteCommand;
????????}
????????//?The?specific?ExecuteCommand?aciton?will?come?from?the?ViewModel,?the?same?as?CanExecuteCommand
????????private?Action<object>?executeCommand;

????????public?Action<object>?ExecuteCommand
????????{
????????????get?{?return?executeCommand;?}
????????????set?{?executeCommand?=?value;?}
????????}

????????private?Func<object,?bool>?canExecuteCommand;

????????public?Func<object,?bool>?CanExecuteCommand
????????{
????????????get?{?return?canExecuteCommand;?}
????????????set?{?canExecuteCommand?=?value;?}
????????}

????????public?event?EventHandler?CanExecuteChanged;

????????public?bool?CanExecute(object?parameter)
????????{
????????????if?(CanExecuteCommand?!=?null)
????????????{
????????????????return?this.CanExecuteCommand(parameter);
????????????}
????????????else
????????????{
????????????????return?true;
????????????}
????????}

????????public?void?Execute(object?parameter)
????????{
????????????if?(this.ExecuteCommand?!=?null)?this.ExecuteCommand(parameter);
????????}

????????public?void?RaiseCanExecuteChanged()
????????{
????????????if?(CanExecuteChanged?!=?null)
????????????{
????????????????CanExecuteChanged(this,?EventArgs.Empty);
????????????}
????????}
????}
}
注:ICommand中有兩個(gè)方法CanExecute和Execute必須實(shí)現(xiàn),這兩個(gè)方法分別對(duì)應(yīng)著當(dāng)Command調(diào)用時(shí)判斷是否能執(zhí)行和具體執(zhí)行邏輯。

4?ViewModelBase類

using?System.ComponentModel;

namespace?MVVM.ViewModel
{
????public?class?ViewModelBase?:?INotifyPropertyChanged
????{
????????public?event?PropertyChangedEventHandler?PropertyChanged;

????????public?void?RaisePropertyChanged(string?propertyName)
????????{
????????????if?(this.PropertyChanged?!=?null)
????????????{
????????????????this.PropertyChanged(this,?new?PropertyChangedEventArgs(propertyName));
????????????}
????????}
????}
}
注:ViewModelBase實(shí)現(xiàn)了接口INotifyPropertyChanged,?在該接口中有一個(gè)PropertyChanged事件,?當(dāng)ViewModel中的Property改變時(shí),允許觸發(fā)PropertyChanged事件,繼而重新綁定數(shù)據(jù)到UI上。
5?CaculatorViewModel類
using?System.Windows.Input;
using?MVVM.Model;
using?MVVMDemo.Commands;

namespace?MVVM.ViewModel
{
????public?class?CaculatorViewModel:ViewModelBase
????{
????????#region?Fields

????????private?int?num1;
????????private?int?num2;
????????private?int?result;
????????private?CaculatorModel?model;

????????#endregion

????????#region?Properties

????????public?int?Num1
????????{
????????????get?
????????????{
????????????????return?num1;
????????????}
????????????set
????????????{
????????????????num1?=?value;
????????????????this.RaisePropertyChanged("Num1");
????????????}
????????}

????????public?int?Num2
????????{
????????????get
????????????{
????????????????return?num2;
????????????}
????????????set
????????????{
????????????????num2?=?value;
????????????????this.RaisePropertyChanged("Num2");
????????????}
????????}

????????public?int?Result
????????{
????????????get
????????????{
????????????????return?result;
????????????}
????????????set
????????????{
????????????????result?=?value;
????????????????this.RaisePropertyChanged("Result");
????????????}
????????}

????????#endregion

????????#region?Commands

????????public?ICommand?CaculateCommand{get;set;}
????????public?ICommand?ClearCommand?{?get;?set;?}

????????#endregion

????????#region?Methods

????????public?void?Add(object?param)
????????{
????????????Result?=?Num1?+?Num2;
????????}

????????public?void?Clear(object?param)
????????{
????????????Result?=?0;
????????????Num1?=?0;
????????????Num2?=?0;
????????}

????????public?void?InitilizeModelData()
????????{
????????????//?In?gernal,?the?data?comes?from?database
????????????var?model?=?new?CaculatorModel()
????????????{
????????????????Num1?=?1,
????????????????Num2?=?1,
????????????????Result?=?2
????????????};

????????????Num1?=?model.Num1;
????????????Num2?=?model.Num2;
????????????Result?=?model.Result;
????????}

????????public?CaculatorViewModel()
????????{
????????????CaculateCommand?=?new?DelegateCommand(Add,?null);
????????????ClearCommand??=?new?DelegateCommand(Clear,?null);

????????????InitilizeModelData();
????????}

????????#endregion
????}
}
6?簡(jiǎn)單計(jì)算器的UI

?

該View所對(duì)應(yīng)的XAML文件如下:
<Window?x:Class="MVVM.View.CaculatorView"
????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????????Title="CaculatorView"?Height="300"?Width="682">
????<Grid?Width="596">
????????<TextBox?Height="23"?HorizontalAlignment="Left"?Margin="41,90,0,0"?Name="txtNum1"?VerticalAlignment="Top"?Width="120"?Text="{Binding?Num1}"/>
????????<TextBox?Height="25"?HorizontalAlignment="Left"?Margin="195,88,0,0"?Name="txtNum2"?VerticalAlignment="Top"?Width="120"?Text="{Binding?Num2}"/>
????????<Label?Content="+"?Height="28"?HorizontalAlignment="Left"?Margin="167,88,0,0"?Name="label1"?VerticalAlignment="Top"?/>
????????<TextBox?Height="25"?HorizontalAlignment="Left"?Margin="364,88,0,0"?Name="textBox5"?VerticalAlignment="Top"?Width="120"??Text="{Binding?Result}"/>
????????<Button?Content"="?Height="23"?HorizontalAlignment="Left"?Margin="328,90,0,0"?Name="button1"?VerticalAlignment="Top"?Width="28"?Command="{Binding?CaculateCommand}"?/>
????????<Button?Content="Clear"?Height="26"?HorizontalAlignment="Left"?Margin="501,88,0,0"?Name="button2"?VerticalAlignment="Top"?Width="45"?Command="{Binding?ClearCommand}"?/>
????</Grid>
</Window>
6.?View的Code-Behind
using?System.Windows;
using?MVVM.ViewModel;

namespace?MVVM.View
{
????///?<summary>
????///?CaculatorView.xaml?的ì?交?互£¤邏?輯-
????///?</summary>
????public?partial?class?CaculatorView?:?Window
????{
????????public?CaculatorView()
????????{
????????????InitializeComponent();
????????????this.DataContext?=?new?CaculatorViewModel();
????????}
????}
}
注:這里講View的DataContext設(shè)為CaculatorViewModel實(shí)例,至此,View和ViewModel建立關(guān)聯(lián)。

轉(zhuǎn)載于:https://www.cnblogs.com/zuochanzi/p/6283007.html

總結(jié)

以上是生活随笔為你收集整理的什么是MVVM模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。