8.1 Prism 的定位与学习方式
学习目标
读完本篇,你应能说明 Prism 解决什么问题、如何与已有 MVVM 知识配合,以及为什么本专题固定使用一个版本。先掌握属性通知、命令和TaskDesk 实战,再进入这里。
为什么学习 Prism
小型 WPF 应用可以用一个窗口、几个 ViewModel 和 MVVM Toolkit 完成。页面逐渐增加后,你会开始反复处理这些问题:谁创建页面与依赖?哪个区域显示哪个页面?切换时是否保留实例?有未保存输入时怎样询问用户?两个独立功能怎样发送消息?
Prism 为这些问题提供一组协作机制:容器集成、ViewModelLocator、Region 导航、对话框服务、事件聚合和模块初始化。它建立在 WPF 的绑定、控件和线程规则之上;学习 Prism 时仍然需要理解这些基础。
| 你熟悉的后端概念 | Prism 中的相关能力 | 迁移时需要注意 |
|---|---|---|
| 启动时注册服务 | PrismApplication 与容器注册 | 同一应用要有明确的组合入口 |
| 按模块组织功能 | IModule 与模块目录 | 模块不是每次点击创建的请求 scope |
| 路由与参数 | Region 导航名和导航参数 | 切换发生在窗口内部,不是 HTTP 请求 |
| 发布订阅 | EventAggregator | 本例是进程内消息,没有持久化或跨进程投递 |
| 服务接口隔离实现 | IDialogService | 对话框仍受 UI 线程和窗口生命周期约束 |
例如“任务页通知 Shell 已新增任务”,可以通过事件通信;“任务页请求服务新增任务”,通常继续使用明确的服务方法。把所有调用改成事件会隐藏依赖和执行次序,应根据关系选择机制。
与 MVVM Toolkit 怎样配合
MVVM Toolkit 着重减少属性通知、命令和消息等代码;Prism 还提供页面组织、导航和模块生命周期。你可以用 Prism 负责导航,让某些 ViewModel 继承 Toolkit 的 ObservableObject,再实现 Prism 的导航接口。
| 需求 | 本专题使用 | 已学过的对应能力 |
|---|---|---|
| 属性通知 | BindableBase.SetProperty | ObservableObject、ObservableProperty |
| 同步命令 | DelegateCommand | RelayCommand |
| 异步操作 | AsyncDelegateCommand | AsyncRelayCommand |
| 页面选择与复用 | Region 导航 | CurrentViewModel 与 DataTemplate |
| 跨页面通知 | EventAggregator | 显式回调或工具包消息机制 |
一个类不能同时继承 BindableBase 和 ObservableObject,不要为了“配合使用”重复添加通知实现。同一对象也不必为一个按钮同时提供两种命令。第一次学习本专题,采用 Prism 的通知和命令,便于观察完整体系;后续再按项目需求组合。
Prism 的 DryIoc 容器可以作为组合入口。原 TaskDesk 使用 Generic Host 和 Microsoft DI,学习迁移时要先决定哪些服务由谁创建,避免两个根容器各自持有一份“全局状态”。后端已有的纯服务接口仍可继续使用。
版本约定:Prism 9.0.537
专题与配套示例使用 .NET 10 WPF,固定安装 Prism.DryIoc 9.0.537。该包会带入匹配的 Prism WPF 和容器适配依赖。文档查询选择官方 9.0 版本;看到当前版本或旧博客时,先确认 API 是否一致。
dotnet add package Prism.DryIoc --version 9.0.537
Prism 9 的若干名称与旧版本不同:
| 主题 | 本专题采用的 API |
|---|---|
| Region 与导航接口 | Prism.Navigation.Regions |
| 导航参数与结果 | Prism.Navigation,结果使用 Success、Exception |
| 对话框服务 | Prism.Dialogs |
| 请求关闭对话框 | DialogCloseListener RequestClose,通过 Invoke 调用 |
| 异步命令 | Prism 9 提供 AsyncDelegateCommand |
部分官方 Region 文章也保留旧示例名称。遇到 Prism.Regions、导航结果 Result/Error 或对话框的 RequestClose 事件时,先对照本专题和已安装包;不要把这些片段直接混在一起。对话框结果的 Result 仍表示 ButtonResult,它与导航结果是两种对象。
:::info 包与许可 Prism 9 使用社区/商业许可,和旧版的 MIT 许可不同。学习和企业采用时,应按照官方许可及包中附带的条款选择适用许可。这里固定包版本是为了让代码和讲解可以对应。 :::
本专题怎么学
先完成启动、容器与自动关联,让窗口与 ViewModel 正确连接;随后学习通知和命令、Region 导航、对话框、事件聚合和模块。最后运行PrismStudy 实战。
PrismStudy 使用本地内存任务,先验证页面组织;你已有的 TaskDesk API 可作为后续接入练习。完整源码在本地 examples/PrismStudy,原 TaskDesk 仍适合复习异步 HTTP 与状态管理。
常见问题
装了 Prism,绑定为什么仍不更新? Prism 不会替所有普通属性发送通知。要正确设置 DataContext,并通过可通知的属性 setter 更新值。
模块是否就是一个 DLL? 模块是功能的注册与初始化单元,可以先放在一个程序集里。拆程序集、按需加载和插件发现是后续设计决策。
动手练习与验收
列出一个业务桌面客户端的三个页面,说明哪些状态属于页面、哪些服务在应用内共享;再挑出两种页面间关系,分别使用服务调用或事件。验收: 能解释选择原因,知道导航不会自动创建 HTTP 请求 scope,并能找到当前安装的 Prism 包版本。