前言
学习一下Prism。
1.Prism
Prism框架提供了一套丰富的工具、类和模块,帮助开发人员实现以下功能:
- 模块化:Prism框架支持将应用程序拆分为多个模块,每个模块具有自己的功能和视图。这种模块化的设计使得应用程序更加灵活和可扩展。
- 导航:Prism框架提供了导航功能,可以方便地在不同的视图之间进行导航和交互。开发人员可以定义导航路径和参数,以及处理导航事件。
- 依赖注入:Prism框架内置了一个轻量级的依赖注入容器,可以帮助开发人员管理和解决组件之间的依赖关系。这样可以提高代码的可测试性和可维护性。
- 事件聚合器:Prism框架提供了一个事件聚合器,可以帮助不同模块之间进行解耦和通信。开发人员可以通过发布和订阅事件来实现模块之间的交互。
- 命令绑定:Prism框架支持命令绑定,可以将用户操作和后台逻辑进行绑定。这样可以更好地分离用户界面和业务逻辑。
- 可测试性:Prism框架的设计考虑了应用程序的可测试性,提供了一些工具和模式,帮助开发人员编写可测试的代码。
1.1创建WPF
创建WPF程序,我是基于net8框架创建。

安装包
Prism.DryIoc

修改App.xaml
继承PrismApplication并实现CreateShell(设置启动页)、RegisterTypes(注册服务)
因为即设置了启动页,也设置了StartupUri,所以弹出了俩个窗体。

1.2创建Prism
打开vs,我的是vs2022,管理扩展

查找Prism,安装 Prism Template Pack

安装完后,关闭所有vs,再打开就会自动修改vs2022的配置,等待修改完毕即可

创建WPF Prism Full项目

选择DryIoc

创建成功

2.Prism区域
2.1实现区域切换
创建ViewModels、Views文件夹内,注意名称,容器就是根据命名空间找到对应的类。
新建三个用户控件,并在App注入服务。

需要修改MainWindow的命名空间,加上Views,要不容器无法找到,算是一个小坑。
MainWindow加上几个按钮和ContentControl用于区域切换。
button加上参数,用于后台命令根据名称切换界面。
prism:ViewModelLocator.AutoWireViewModel="True"。

MainWindowViewModel实现BindableBase。
实现显示内容命令(DelegateCommand),根据前台传入的参数显示区域。

2.2解耦优化
注入IRegionManager(区域管理),通过IRegionManager去实例化用户控件。

App重载一下RegisterForNavigation。
如果不想使用别名需要全名,这里使用别名。

3.Prism模块化
3.1引用模块
创建WPF程序模块A和模块B


删除WPF程序自带的一些文件。

然后把Peng.MoudleA和Peng.MoudleB输出类型改为类库。

为什么创建WPF程序而不是类库?
因为类库不能添加WPF窗口、用户控件等文件,项目需要加载模块的窗口、用户控件等。

ModuleA、ModuleB都引用Prism.DryIoc。
<ItemGroup>
<PackageReference Include="Prism.DryIoc" Version="8.1.97" />
</ItemGroup>

实现IModule,把MoudleA和MoudleB注入到IOC容器中。

主程序引入MoudleA和MoudleB,并且改变命令参数为MoudleAUC、MoudleBUC,此名称对应模块中用户控件名称。

在主程序添加MoudleA和MoudleB。

3.2动态加载
添加Modules文件夹,并且把生成后的MoudleA和MoudleB移到Modules文件夹下。

选择Peng.MoudleA.dll和Peng.MoudleBdll修改属性始终复制。

主程序不用引入Peng.MoudleA和Peng.MoudleB了,会动态加载Modules目录下的dll。

4.导航
4.1传参
ViewModelLocator.AutoWireViewModel="True"可以通过命名的形式让控件找到对应的视图,但是一旦名字写错就容易找不到,所以一般不建议这么使用,可以注入的时候指定控件和视图。

通过添加NavigationParameters字典传参。

ModuleAUCViewModel需要实现INavigationAware。
通过判断是否存在Key获取参数值,然后双向绑定显示界面。

重新生成后,记得替换Modules目录下的dll。

4.2导航后退
增加后退按钮,绑定后退命令。

实现后退命令。
第一次加载的时候Journal为null,所以需要判断非null。

传参数的时候需要添加导航记录。

实现IConfirmNavigationRequest,这里不需要INavigationAware,因为IConfirmNavigationRequest继承了INavigationAware

5.Prism对话框
新建Peng.MoudleC用于对话框服务。
简单写一下界面,一个Title,一个显示获取的参数,还有俩个按钮。
ModuleCUCViewModel实现BindableBase、IDialogAware。
BindableBase用于和界面绑定。
IDialogAware是对话框服务。

实现IDialogAware几个方法。
RequestClose是返回对话框状态,在确定和取消命令的时候返回结果。
在OnDialogOpened时获取传入的参数。
在Confirm时返回参数。

最后显示注入对话框服务。

主界面添加一个按钮和一个文本框用于打开对话框和显示对话框传入的参数。
添加ShowDialogCmd显示对话框命令。
添加DialogService对话框服务。
在DialogService.ShowDialog回调函数中获取对话框返回结果。

重新生成后记得改Peng.MoudleC.dll属性为始终复制。

6.发布订阅
实现PubSubEvent,T
是订阅方法的参数类型。

代码比较简单,简单赘述一下。
主界面添加三个按钮:发布、订阅、取消订阅,绑定三个命令。
IEventAggregator是发布订阅的服务,默认已经注入,可以通过构造函数方式获取即可。
Publish:发布事件。
Subscribe:订阅事件。
CancelSub:取消订阅。
