以下内容基于Prism6.3(.Net Framwork 4.5)
说明
Prism注入容器目前支持5种,Unity、MEF、Ninject、AutoFac、DryIoc。目前框架我们选择Unity作为Prism的注入容器。
UnityBootstrapper执行流程以及方法说明(按执行顺序)
- 执行流程图
- Run(bool runWithDefaultConfiguration)。在程序入口一般调用无参的Run()多态方法,runWithDefaultConfiguration默认为True
- ILoggerFacade CreateLogger()。Prism框架没有实现默认的Log服务,需要使用框架者实现ILoggerFacade接口,这里返回自己实现的ILoggerFacade 的实例。使用log4net组件:https://www.cnblogs.com/youngytj/p/5672306.html
- IModuleCatalog CreateModuleCatalog()。创建模块目录。Prism提供了4中方式来创建模块目录
- 4.1 通过App.config。通过这个方案需要返回一个ConfigurationModuleCatalog对象
- 4.2 通过Xaml。通过这个方案需要请查看https://www.cnblogs.com/tianciliangen/p/4955753.html
- 4.3 通过文件目录。通过这个方案需要返回一个DirectoryModuleCatalog对象
- 4.4 通过代码。通过这种方案需要写在第5小节的重载方法中
- void ConfigureModuleCatalog()。配置模块目录。通过代码来加入模块,可以用ModuleInfo 类来标识某个模块
- IUnityContainer CreateContainer()。创建依赖容器。我们选择Unity,这个不需要重载
- void ConfigureContainer()。配置依赖容器。这个也不需要重载
- void ConfigureServiceLocator()。配置服务加载器。Prism中默认使用ServiceLocator作为服务加载器
- void ConfigureViewModelLocator()。使用代码注册配置View和ViewModel的对应关系。Prism提供了另一种配置V-VM关系的方法,该方法使用附加属性提供了一种约定胜于配置的定义方案,在View视图根节点添加该附加属性ViewModelLocator.AutoWireViewModel="True",Prism框架会自动注册
- RegionAdapterMappings ConfigureRegionAdapterMappings()。注册自定义的区域适配器。Prism提供了四种布局可以作为区域容器。TabControl、Selector、ItemsControl、ContentControl。如果只用到这几个布局控件,则一般不需要重载这个方法。如果想用到其他布局控件例如StackPanel,那么我们需要写一个自定义的区域适配器,并在这个重载方法中进行注册。自定义的区域适配器需要继承RegionAdapterBase<T>。在自定义区域适配器中可以附加该区域的行为(Behavior),AttachDefaultBehaviors和AttachBehaviors。前者默认是附加在下一节的重载方法中配置的行为,也可以不调用Base方法,自己注册行为,但一般不需要修改;一般会为自定义区域适配器添加个性行为是在后者(AttachBehaviors)中添加。
- IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()。配置默认的区域行为。Prism为上小节中说到的四个布局容器默认添加了行为(五种默认行为:https://blogs.msdn.microsoft.com/erwinvandervalk/2008/11/21/prism-v2-drop-6-composite-application-guidance-for-wpf-and-silverlight/)。区域的目标对象现在只支持UserControl控件
- DependencyObject CreateShell()。返回应用程序的主窗体
- void InitializeShell()。初始化主窗体,一般弹出主窗体
- void InitializeModules()。初始化模块。这个一般不用重载,一般有第5节的就行
Module 模块
Prism提供了各个模块之间的松耦合。Prism中模块需要实现IModule接口。该接口只有一个方法,在该方法中需要注册该模块想为框架提供的一些视图,服务等。
ModuleManager 在运行时期动态的加载模块
当添加模块时我们声明该模块的初始化方式为OnDemand.OnDemand时,则该模块需要我们手动调用ModuleManager.Load(),才能加载到容器中。
Region Prism提供的区域模型
- 区域模型将整个View(视图)分成各个不同的区域块,各个小的区域块也是一个小的View,有对应的VM。
区域在VIew中一般这样写:
在模块初始化时,将子View注册到某个区域中,这样写:
- 区域上下文的使用:区域上下文一般用于两个View需要联动的情况下,当然,我们也可以用消息进行通信,这里我们讲一下区域上下文的使用方法:
View中的代码如下:
在注册到该区域名称的VIew的后台代码中,这样写:
这样就完成了区域上下文的设置。
RegionManager 区域管理。一般用于View的注册,也就是View和Region的关联
模块之间的通信---EventAggregator和PubSubEvent<TPayload>
Prism提供了一种高内聚松耦合的编程框架,松耦合导致各个模块之间存在物理上的隔离,因此Prism提供了发布者--订阅者机制来进行模块间的通信。首先需要继承PubSubEvent<T>来定义一个容器C,用来装载某种特定的消息,我们再用IEventAggregator聚合事件的实例,去传输(发布和订阅)这个容器。
消息的发布很简单,大概象这样写:
消息的订阅方法有多态实现,这里说一下各个参数的意思和使用场景:
- 参数1:订阅者处理发布者执行的方法
- 参数2:该参数是一个枚举类型,PublisherThread:表示参数1的方法和发布方法顺序(同步)执行,在一个线程中;UIThread和BackgroundThread:两个方法是异步执行,两者唯一的区别是,前者代表参数1的方法执行在UI线程中,后者执行在线程池的线程中,由此我们可以看出,发布者发布消息是异步发送。
- 参数3:发布者是否保持订阅者实例。这样订阅者就不会被垃圾回收
- 参数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个使用方法都是通过观察某个属性(该属性要求执行更改通知特性)来去更新命令可用性的方式。
CompositeCommand命令模型:这个是组合命令,就是将很多命令挂在该命令下面,统一触发。