以下內容基于Prism6.3(.Net Framwork 4.5)
說明
Prism注入容器目前支持5種,Unity、MEF、Ninject、AutoFac、DryIoc。目前框架我們選擇Unity作為Prism的注入容器。
UnityBootstrapper執(zhí)行流程以及方法說明(按執(zhí)行順序)
- 執(zhí)行流程圖

- Run(bool runWithDefaultConfiguration)。在程序入口一般調用無參的Run()多態(tài)方法,runWithDefaultConfiguration默認為True
- ILoggerFacade CreateLogger()。Prism框架沒有實現(xiàn)默認的Log服務,需要使用框架者實現(xiàn)ILoggerFacade接口,這里返回自己實現(xiàn)的ILoggerFacade 的實例。使用log4net組件:https://www.cnblogs.com/youngytj/p/5672306.html
- IModuleCatalog CreateModuleCatalog()。創(chuàng)建模塊目錄。Prism提供了4中方式來創(chuàng)建模塊目錄
- 4.1 通過App.config。通過這個方案需要返回一個ConfigurationModuleCatalog對象
- 4.2 通過Xaml。通過這個方案需要請查看https://www.cnblogs.com/tianciliangen/p/4955753.html
- 4.3 通過文件目錄。通過這個方案需要返回一個DirectoryModuleCatalog對象
- 4.4 通過代碼。通過這種方案需要寫在第5小節(jié)的重載方法中
- void ConfigureModuleCatalog()。配置模塊目錄。通過代碼來加入模塊,可以用ModuleInfo 類來標識某個模塊
- IUnityContainer CreateContainer()。創(chuàng)建依賴容器。我們選擇Unity,這個不需要重載
- void ConfigureContainer()。配置依賴容器。這個也不需要重載
- void ConfigureServiceLocator()。配置服務加載器。Prism中默認使用ServiceLocator作為服務加載器
- void ConfigureViewModelLocator()。使用代碼注冊配置View和ViewModel的對應關系。Prism提供了另一種配置V-VM關系的方法,該方法使用附加屬性提供了一種約定勝于配置的定義方案,在View視圖根節(jié)點添加該附加屬性ViewModelLocator.AutoWireViewModel="True",Prism框架會自動注冊
- RegionAdapterMappings ConfigureRegionAdapterMappings()。注冊自定義的區(qū)域適配器。Prism提供了四種布局可以作為區(qū)域容器。TabControl、Selector、ItemsControl、ContentControl。如果只用到這幾個布局控件,則一般不需要重載這個方法。如果想用到其他布局控件例如StackPanel,那么我們需要寫一個自定義的區(qū)域適配器,并在這個重載方法中進行注冊。自定義的區(qū)域適配器需要繼承RegionAdapterBase<T>。在自定義區(qū)域適配器中可以附加該區(qū)域的行為(Behavior),AttachDefaultBehaviors和AttachBehaviors。前者默認是附加在下一節(jié)的重載方法中配置的行為,也可以不調用Base方法,自己注冊行為,但一般不需要修改;一般會為自定義區(qū)域適配器添加個性行為是在后者(AttachBehaviors)中添加。
- IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()。配置默認的區(qū)域行為。Prism為上小節(jié)中說到的四個布局容器默認添加了行為(五種默認行為:https://blogs.msdn.microsoft.com/erwinvandervalk/2008/11/21/prism-v2-drop-6-composite-application-guidance-for-wpf-and-silverlight/)。區(qū)域的目標對象現(xiàn)在只支持UserControl控件
- DependencyObject CreateShell()。返回應用程序的主窗體
- void InitializeShell()。初始化主窗體,一般彈出主窗體
- void InitializeModules()。初始化模塊。這個一般不用重載,一般有第5節(jié)的就行
Module 模塊
Prism提供了各個模塊之間的松耦合。Prism中模塊需要實現(xiàn)IModule接口。該接口只有一個方法,在該方法中需要注冊該模塊想為框架提供的一些視圖,服務等。
ModuleManager 在運行時期動態(tài)的加載模塊
當添加模塊時我們聲明該模塊的初始化方式為OnDemand.OnDemand時,則該模塊需要我們手動調用ModuleManager.Load(),才能加載到容器中。
Region Prism提供的區(qū)域模型
- 區(qū)域模型將整個View(視圖)分成各個不同的區(qū)域塊,各個小的區(qū)域塊也是一個小的View,有對應的VM。
區(qū)域在VIew中一般這樣寫:

在模塊初始化時,將子View注冊到某個區(qū)域中,這樣寫:

- 區(qū)域上下文的使用:區(qū)域上下文一般用于兩個View需要聯(lián)動的情況下,當然,我們也可以用消息進行通信,這里我們講一下區(qū)域上下文的使用方法:
View中的代碼如下:

在注冊到該區(qū)域名稱的VIew的后臺代碼中,這樣寫:

這樣就完成了區(qū)域上下文的設置。
RegionManager 區(qū)域管理。一般用于View的注冊,也就是View和Region的關聯(lián)
模塊之間的通信---EventAggregator和PubSubEvent<TPayload>
Prism提供了一種高內聚松耦合的編程框架,松耦合導致各個模塊之間存在物理上的隔離,因此Prism提供了發(fā)布者--訂閱者機制來進行模塊間的通信。首先需要繼承PubSubEvent<T>來定義一個容器C,用來裝載某種特定的消息,我們再用IEventAggregator聚合事件的實例,去傳輸(發(fā)布和訂閱)這個容器。
消息的發(fā)布很簡單,大概象這樣寫:

消息的訂閱方法有多態(tài)實現(xiàn),這里說一下各個參數(shù)的意思和使用場景:

- 參數(shù)1:訂閱者處理發(fā)布者執(zhí)行的方法
- 參數(shù)2:該參數(shù)是一個枚舉類型,PublisherThread:表示參數(shù)1的方法和發(fā)布方法順序(同步)執(zhí)行,在一個線程中;UIThread和BackgroundThread:兩個方法是異步執(zhí)行,兩者唯一的區(qū)別是,前者代表參數(shù)1的方法執(zhí)行在UI線程中,后者執(zhí)行在線程池的線程中,由此我們可以看出,發(fā)布者發(fā)布消息是異步發(fā)送。
- 參數(shù)3:發(fā)布者是否保持訂閱者實例。這樣訂閱者就不會被垃圾回收
- 參數(shù)4:消息過濾。只訂閱某種消息中自己感興趣的消息。
VM到V的動作傳遞
- MVVM設計模式里V(視圖)上的動作通過Command或者Triggers---CallMethodAction組合將動作傳遞到VM中。
- 如果需要在VM中將動作傳遞給V(視圖),比如關閉窗體,需要用到InteractionRequest<INotification>通知類。
VM中一半寫法:

V(視圖)中寫法:

Prism下的MVVM模型
Prism下的MVVM名稱空間一共5個類,一般來說VM不需要繼承任何類,不過為了屬性有更改通知的能力,我們一般繼承BindableBase抽象類。對于View,上文也提到過,Prism采用約定勝于配置的策略,通過附加屬性ViewModelLocator.AutoWireViewModel=“true”,Prism自動會將View和ViewModel進行上下文綁定。當時我們也可以使用代碼方式進行綁定,這里就需要用到該名稱空間下的另一個類ViewModelLocationProvider,通過Register方法進行注冊,但View中的附加屬性是必不可少的。
Command 命令
Prism提供了兩種命令模型DelegateCommand和CompositeCommand。
DelegateCommand命令模型:就是一般的命令模型,像普通的命令一樣,提供了ExcuteAction和CanExcuteAction。但該模型為命令的可用性更新提供了便利,看一下代碼:

第一個使用場景不做解釋,第2,3,4個使用方法都是通過觀察某個屬性(該屬性要求執(zhí)行更改通知特性)來去更新命令可用性的方式。
CompositeCommand命令模型:這個是組合命令,就是將很多命令掛在該命令下面,統(tǒng)一觸發(fā)。