1. 程式人生 > >WPF_MVVM 開發的幾種模式討論

WPF_MVVM 開發的幾種模式討論

   在WPF系(包括SL,WP或者Win8)應用開發中,MVVM是個老生常談的問題。初學者可能不會有感覺,但當你寫一個核心邏輯能在各種平臺上無縫移植,而只需改改UI的時候,那種快感是無法用語言來形容的。

   筆者當初接觸時,對MVVM並不以為然,編了很多程式碼以後,反過來看MVVM for WPF的經典文章以後,才若有頓悟。標準的MVVM把程式分成了Model, ViewModel和 View三個部分,但方法是死的,人是活的。我一般的做法是邏輯寫一個,View寫一個,沒有那麼嚴格。為了方便討論,我們把ViewModel和Model合稱Model, View還是View, 分別代表邏輯和介面。分離是肯定的,可是在程式中終究是要把View和Model在某個地方結合起來。 本文就討論下幾種結合的方式。

1. 標準MVVM(由View例項化Model)

     標準的MVVM,做法當然是先設計Model, 然後再設計View, 在View的程式碼裡有且僅有這麼幾句話:

複製程式碼
 public partial class PluginMangerUI : UserControl
    {
     
        public PluginMangerUI()
        {
            this.InitializeComponent();
            PluginManager manager = new PluginManager();
            this.DataContext = manager;
        }
    }
複製程式碼
 基本的邏輯結構可以用下圖來表示。不同的庫是由自底向上的方式設計的。

image

    這種由View呼叫Model, 並具體由View負責Model例項化的方式是最為普遍的,非常適合於需要跨平臺的應用。當然,Model並不知道View的存在,因此View要承擔所有的介面邏輯,好在WPF已經給出了足夠多的解決方案,觸發器,模板。基本絕大多數需求都能滿足。

2. 外掛結構(Model例項化View)

     這種做法,是筆者經常用的。在Model裡,通過以下程式碼來實現介面生成

複製程式碼
internal class ViewExample : UserControl { }

    public class ModelExample : IView
    {

        private readonly ViewExample view;
        public ModelExample()
        {
            this.view = new ViewExample();
        }
        public object UserControl
        {
            get
            {
                return this.view;
            }
        }
複製程式碼

   肯定會有同學問道,怎麼會有這麼奇怪的寫法?這種做法的最常見場合應該是外掛系統。一個個的Model其實是一個個的外掛,它們應該具備自治性。因此,應該由自身負責介面的產生。

   它的好處是可以通過Model更加精細的調節View的行為,你可以在任何時候獲得View內部ListBox的SelectIndex, 而不用麻煩的用Binding。 打個比方說,遊戲開發中,你需要隨時控制物體的運動速度和方向,這樣Model就必須控制View. 繫結很難解決這類問題。

   我不知道有多少同學在WPF中使用外掛的設計思想。若按外掛的思路,庫應該按功能劃分。在這種設計思路下,不同的庫便不是自下而上的分層了,而是通過領域和功能分層,如下圖:

image

  每一個功能庫都有完整的自治性,當你將該功能庫拷貝到主框架之下時,它就會自動載入,由Model負責View的生成。一切合情合理。

  3. 組裝車間(第三方組裝View和Model)

   這種思路來自於工廠方法,類似於裝配車間,View和Model都不負責互相的例項化。而有一個“管理器”負責組裝它們。這樣的好處在於可配置。你可以通過配置檔案動態的改變View.

    我記得一種比較著名的WPF嚮導(Wizard)就是這樣的設計思路:

複製程式碼
private static List<CompleteStep<DataProcessTask>> CreateSteps(DataProcessTask o)
        {
            var welcomeModel = new WelcomeModel(o);
            var step1ViewModel = new UserCoreModel(o);
            var step2ViewModel = new UserDataModel(o);
            var step3ViewModel = new ConnectModel(o);
            var step6ViewModel = new FinishModel(o);

            return new List<CompleteStep<DataProcessTask>>
                       {
                           /// Each step contains a ViewModel and a View type (the type representing the actual Xaml to be shown).
                           new CompleteStep<DataProcessTask>
                               {ViewModel = welcomeModel, ViewType = typeof (Welcome), Visited = true},
                           new CompleteStep<DataProcessTask> {ViewModel = step1ViewModel, ViewType = typeof (UserCore)},
                           new CompleteStep<DataProcessTask>
                               {ViewModel = step2ViewModel, ViewType = typeof (UserDataView)},
                           new CompleteStep<DataProcessTask> {ViewModel = step3ViewModel, ViewType = typeof (Connect)},
                           new CompleteStep<DataProcessTask> {ViewModel = step6ViewModel, ViewType = typeof (Finish)}
                       };
        }
複製程式碼

    如上圖所示,DataProcessTask類是控制整個流程的核心,第一步先例項化所需的ViewModel, 第二部,通過構建一個List列表,將View的Type的方法傳到列表中。最終管理器通過反射來例項化View,並將DataContext繫結到對應的ViewModel完成整個組裝過程。

    可以看出,這種做法徹底的隔絕了View和Model, 同時通過配置選項,可以隨時修改View。可謂是一種不錯的設計。 但是,必需看到,對於View來說,Model沒有任何管理的許可權。下圖展示了它的基本邏輯:

image

  如果最終你依舊需要兩邊互相控制,可以考慮採用dynamic關鍵字。

4. 總結

    其實沒有哪種方式是最好的,完全是看你對整個系統的設計需求。但不論如何,介面和邏輯的分離,這是毋庸置疑的。下面的表格總結了幾種做法的特點和適用場合:

名稱 組裝邏輯 適用場合 缺點 備註
標準MVVM View例項化Model 常用的跨平臺場合 Model無法控制任何View 適用於自底向上的分層設計
Model例項化View Model例項化View 外掛結構或用於遊戲開發 存在一定的耦合 適用於按功能劃分的外掛型類庫設計,或要求Model大量控制View的場合
組裝車間 第三方管理器例項化和組裝Model和View 可動態替換所有View 兩者徹底隔絕,沒有控制靈活性 大型系統的嚴格設計

    當然,如果用MVVMLight等第三方類庫的話,就應該按照它的方案去開發。但我們的原則是,解決問題,但不要引入更復雜的問題。為了解耦,搞了大量的複雜邏輯,反而捨本逐末。

相關推薦

WPF_MVVM 開發模式討論

   在WPF系(包括SL,WP或者Win8)應用開發中,MVVM是個老生常談的問題。初學者可能不會有感覺,但當你寫一個核心邏輯能在各種平臺上無縫移植,而只需改改UI的時候,那種快感是無法用語言來形容的。    筆者當初接觸時,對MVVM並不以為然,編了很多程式碼以後,反過來看MVVM for WPF的經典

交易所系統有哪模式?交易系統開發,imToken錢包開發

易信 完成後 操作 愛好 數字 比例 線下 借貸 風險 交易所系統有哪幾種模式?交易系統開發,imToken錢包開發 交易系統有哪幾種模式? (1)OTC交易系統 OTC:是一套獨立於交易所外的線下購買數字資產的平臺,任何人都可以在該平臺上發布購買/出售廣告,購買/出售用戶

hybrid模式

訪問 andro 原生應用 需要 ble 依賴 綁定 內核 client native和web適合的場景 Native: 用戶體驗要求高 業務變動很小(如首頁) 性能要求高 Web: 業務變化頻繁(如廣告) 性能要求低 展

運行Spark程序的模式

etc 屏幕 角色 ast java_home enabled driver env ram 一. local 模式 -- 所有程序都運行在一個JVM中,主要用於開發時測試 無需開啟任何服務,可直接運行 ./bin/run-example 或 ./bin/spark-

總結js面向對象調用的模式

跟著 模式 也會 name proto bject prot .proto 混合模式   一、工廠模式:類似於function func(A,B){ var obj=new Object(); obj.A=A; obj.B=B; return obj;}; var obt

JavaScript中創建對象的模式

-c aps lang mage pen lin round property mar 代碼如下: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <met

vim的模式&快捷鍵

後退 -h shell命令 識別 需要 刪除 .html 頁簽 空字符 vim的幾種模式&快捷鍵 2017年01月01日 14:05:24 閱讀數:3060 一.vim的模式 基本上vim可以分為三種模式:命令模式,插入模式和底行模式,其實vi

建立物件的模式

一般建立物件是用以下兩種方式 new object建立物件: var Person = new Object(); Person.name = "張三"; Person.age = "18"; Person.job = "123"; 或者,物件字面量的方式: var Person =

創建對象的模式

開發 組合 無法 只需要 toolbar 同名 工廠模式 但是 方式 一般創建對象是用以下兩種方式 new object創建對象: var Person = new Object(); Person.name = "張三"; Person.age = "18";

redis模式的部署(Windows下實現)

原文地址:https ://www.cnblogs.com/yu421/p/8081544.html <參考> http://www.cnblogs.com/ruiati/p/6374152.html 1.自行下載redis客戶端.redis官方不支援Windows系統,所以官網

vim的模式

Normal Mode 普通模式 功能:在這種模式下可以移動游標等。 進入:預設進入vim之後,處於這種模式。在其他模式下狂按ESC後進入此模式。 Visual Mode 可視模式 功能:在這種模式下可以選定一些字元、行、多列。 進入:在普通模式下,按v進入。 Insert Mode 插入模式

Atitit 單點登入實現模式架構圖 目錄 1. 因此要點也就以下兩個:儲存信任驗證信任 1 1.1. 共享cookie (最簡單 1 1.2. 通過 url帶token引數跳轉 1 1.3.

Atitit 單點登入實現幾種模式架構圖   目錄 1. 因此要點也就以下兩個:儲存信任驗證信任 1 1.1. 共享cookie (最簡單 1 1.2. 通過 url帶token引數跳轉 1 1.3. 頁面重定向(複雜 1 1.3.1. 父子應用重定向 2

(四)高德地圖之定位的模式

這一節主要實現的功能是地圖定位的幾種模式,包括展示、定位、追隨、旋轉、旋轉位置、跟隨不移動中心點、旋轉不移動中心點、旋轉位置不移動到中心點,我們根據實際需要來選擇用那種模式。下面還是主要從程式碼中來體現,主要部分有註釋。 還是先新建佈局檔案:activity_locationmodesour

DevOps--模式

目錄 模式一 模式二 模式三 本文摘抄自:DevOps的概念與實踐  模式一 敏捷開發模式  通常,在軟體開發專案中,開發會用完所有計劃的時間用於開發功能,這樣會導致無法充分解決IT運維的問題,這就是開發和IT運維以及次優結果之間的永恆的緊張關

spark的模式的比較

在spark的學習中,spark一共有四種模式,分別是: spark基於local spark基於standalone spark基於yarn spark基於metsos   Standalone模式兩種提交任務方式 Standalone-cli

spark 環境搭建及模式測試

spark 環境搭建及幾種模式測試 spark安裝部署spark安裝前的環境準備 需要安裝jdk、scala、hadoop作為前提環境。 1、安裝jdk1.7 先解除安裝自帶的jdk,防止自帶的jdk和安裝的出現衝突。而且自帶的版本較低不能滿足現在軟體對jdk的要求。 使用

字串中判斷存在的模式和效率(string.contains、string.IndexOf、Regex.Match)

 通常情況下,我們判斷一個字串中是否存在某值常常會用string.contains,其實判斷一個字串中存在某值的方法有很多種,最常用的就是前述所說的string.contains,相對來說比較常用的還有string.IndexOf和Regex.Match。直接上程式碼,後面在說些什麼吧,通常情況下功能的實現最

python之檔案操作的模式總結

      檔案操作的幾種模式: "w"                             #write ,清空寫,生成一

SELinux 寬容模式(permissive) 強制模式(enforcing) 關閉(disabled) 模式之間的轉換

在Android的root相關的文章裡經常會看到關於SElinux,Android4.3以後引進SElinux。 ###SELinux 的啟動、關閉與檢視 1、並非所有的 Linux distributions 都支援 SELinux 目前 SELinux 支援三種模式,分別如下:

ASP.NET程式中Session儲存的模式

 ASP.NET程式中Session的sessionState的四種mode模式:Off、InProc、StateServer、SqlServer。 mode 可選的 SessionStateMode 屬性。 指定儲存會話狀態值的位置。有關更多資訊,請參見