MVVM实践教程
???? 算算,從事Silverlight和WPF的開發也有1年多的時間了,雖然時間不算長,雖然還沒有突出的成就,但是感覺也還算一般。
???? 但是,從頭至今都沒有去認真研究和使用過MVVM,雖然它被認為是Silverlight和WPF開發的最佳架構實踐。
???? 我想這里面還是有一些原因,就像一般開始我們始終都不會看好單元測試。直到有一天你體會到它的魅力,它的好處。
???? 最近的項目,卻不得不采用MVVM的模式:UI沒有定,甚至服務端的Service都沒有定,但是不能等到這些都做好才開始展開我們的開發工作。
???? 于是,痛下決心研究MVVM的模式,在學習過程中,發現一些問題。MVVM的使用不僅僅是因為它需要新的思維,使View和ViewModel之間的交互變得更麻煩。這其中還有另外的原因,那就是參考資料不全。
???? 一般網上的資料都是一片簡單的教程,大體都是怎么使用命令,怎么使用Binding的方式來建立應用程序。這些幾乎都出自John Smith的那篇WPF的文章。
???? 而實際上,在開發中,還會遇到其他問題,例如頁面切換,UI事件,并且簡單的示例我們往往弄不清楚各個模塊之間的職責和聯系。因為不能有效實踐,從而被認為會影響開發效率而不被采用。
???? 這里,我將自己學習總結的知識整理成一篇完整的示例,有提供源代碼,源代碼包含比較完整的示例,不僅包含數據綁定和命令的使用,還包含UI事件和UI的切換。相信能解釋大多數遇到的問題。
??? 當然,如果你有更好的實踐和建議,歡迎討論……………
?
?1.MVVM設計模式簡介
?
???? MVVM的設計模式最早于2005年由微軟的WPF和Silverlight架構師John Gossman在他的博客中提到。以下是這篇文章的鏈接:
???? http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx
???? MVVM設計模式基于MVC這種將UI和邏輯分離的結構思想。傳統的.NET平臺下軟件開發如ASP.NET和WPF/Silverlight大多數是基于CodeBehind這樣的方式,我們往往將所有的代碼全部寫在后臺代碼文件中,例如UI操作,業務邏輯操作,IO,數據服務的調用等等。這雖然表面上有利于“開發效率”,實際上項目結構不清晰,各個模塊之間緊密耦合,不利于擴展,不利于測試。
???? MV-X的思想,為.NET平臺下的架構提供一種很好的實踐。使我們可以構建更利于擴展,結構清晰,職責分明,易測試的軟件項目。
???? 但是目前MVVM模式還沒有一個標準的實踐,微軟也還沒有給出相對標準的方案。目前社區討論的主要是MVVM的思想。在實際開發過程中形成了幾種不同的風格。其中以Josh Smith的文章影響比較大:
???? http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
???? 本篇提到的也主要是參考John Smith的思想。
2.采用MVVM設計模式的好處
????
???? 在Silverlight或者WPF中采用MVVM的架構可以獲得以下好處:
???? 1. 項目可測試更高,從而可以執行單元測試
???? 2. 將UI和業務的設計完全分開,View和UnitTest只是ViewModel的兩個不同形式的消費者
???? 3. 有助于我們區別并哪些是UI操作,哪些是業務操作,而不是將他們全混在CodeBehind中
???? 3.項目結構介紹
???? 以下是示例項目的結構截圖:
以下是各模塊之間的聯系:
?
4.WpfMVVMSample.Foundation
???? 提供一些基礎類定義。
5.Model的職責
????
???? Model主要提供基礎實體的屬性以及每個屬性的驗證邏輯。
???? Model不包含數據的調用,但是可以包含簡單的非數據調用的操作,如產生序列號或者合并字段。
???? 對于WCF產生的客戶端代理類,Models中應有與之相對應的類結構定義。
???? Model不依賴于任何項目。
6.IService和Services以及ServiceTest
???? IService是所有網絡數據服務或者IO操作的服務接口。
???? IService中的數據訪問方式以異步為主,見參考示例。
???? Service是真實的數據服務訪問類,是IService的實現。ServiceTest是用于測試ViewModel的IService的實現
7.ViewModel的職責
????
???? ViewModel是MVVM架構中最重要的部分,ViewModel中包含屬性,命令,方法,事件,屬性驗證等邏輯。為了與View以及Model更好的交互來滿足MVVM架構,ViewModel的設計需要注意一些事項或者約束:
??? ViewModel的屬性:ViewModel的屬性是View數據的來源。這些屬性可由三部分組成:
???? 一部分是Model的復制屬性。
??? 另一部分用于控制UI狀態。例如一個彈出窗口的控件可能有一個IsClose的屬性,當操作完成時可以通過這個屬性更改通知View做相應的UI變換或者后面提到的事件通知。
??? 第三部分是一些方法的參數,可以將這些方法的參數設置成相應的屬性綁定到View中的某個控件,然后在執行方法的時候獲取這些屬性,所以一般方法不含參數。
???? ViewModel的命令:ViewModel中的命令用于接受View的用戶輸入,并做相應的處理。我們也可以通過方法實現相同的功能。
???? ViewModel的事件: ViewModel中的事件主要用來通知View做相應的UI變換。它一般在一個處理完成之后觸發,隨后需要View做出相應的非業務的操作。所以一般ViewModel中的事件的訂閱者只是View,除非其他自定義的非View類之間的交互。
???? ViewModel的方法:有些事件是沒有直接提供命令調用的,如自定義的事件。這時候我們可以通過CallMethodAction來調用ViewModel中的方法來完成相應的操作。
8.View及Codebehind
???? View中使用Command:View中的Button等控件可以直接綁定Command屬性調用ViewModel中的Command
???? View中使用CallMethodAction :一些不支持Command的控件,可以用一個CallMethodAction觸發器來執行ViewModel中的方法。注意的是方法當中往往包含一些參數,這些參數一般可以通過給ViewModel設置相應的屬性來綁定到相關的輸入控件,如TextBox。
???? View中使用DataTrigger:除了模型屬性,還有一部分是狀態屬性,這往往是ViewModel通過屬性更改的方式通知View做出相關的UI操作,例如觸發一段動畫,或者切換控件狀態等等。這個時候可以使用一些觸發器,當狀態值不同時做出相應的UI變換。
??? View的CodeBehind中初始化子View的ViewModel上下文:View一般由父View調用,所以View的ViewModel一般由父View來初始化。比如當點擊人脈按鈕,需要顯示人脈的View的時候,就由主框架初始化人脈的ViewModel,并顯示人脈的View。
???? View的CodeBehind中訂閱子View的UI事件:除了通過狀態屬性的變更觸發View中的觸發器,看一種選擇是在View的CodeBehind中訂閱ViewModel的UI事件。
9.View及ViewModel交互模式總結
由以上解析我們可以總結出View和ViewModel的交互模式:
1. 父View在CodeBehind中初始化子ViewModel
2. 父View在CodeBehind中訂閱子ViewModel的UI事件
3. 父View將子ViewModel賦值給子View的DataContext,并顯示子View
4. 父View調用子ViewModel獲取數據的方法,子ViewModel調用數據服務獲取數據
5. ViewModel的數據通過Binding傳遞給View
6. View接受用戶輸入,并通過Command或者CallMethodAction交給ViewModel做業務處理
7. ViewModel處理完成之后觸發UI事件或者更改狀態屬性通知父View
8. 父View做出View變換至新的界面
10. 依賴注入
ViewModel的職責是提供數據給View,并調用底層的數據服務。
為了解除ViewModel和BP的耦合,增加一層IService的接口定義,這也使得我們可以構造不同的IService實現來測試ViewModel。
但是View 在使用ViewModel的時候,ViewModel必須要使用IService對象,所以這里采用依賴注入。通過依賴注入來完全解除View以及ViewModel對于Service的依賴。
示例項目源代碼下載:
http://files.cnblogs.com/hielvis/WpfMVVMSample.rar
|
QQ群:51825601(北京.NET之友技術沙龍) 備注:此群主要用于組織沙龍活動,僅限北京 |
轉載于:https://www.cnblogs.com/hielvis/archive/2011/03/22/1991959.html
總結
- 上一篇: 现在最高级的套装是多少等级的?
- 下一篇: 内衣店加盟多少钱啊?