跳到主要内容

9.2 WPF 核心概念速查

学习目标​

  • 根据需求快速定位 WPF 的对应机制。
  • 记住通知、绑定、命令和线程各自的边界。
  • 用状态表检查 TaskDesk 的交互条件。

概念与使用位置​

概念用来解决什么后端经验对照继续阅读
XAML声明对象树、布局、属性配置与页面声明,但也会创建对象XAML
Grid按行列分配空间页面布局,不是数据表格布局
DataContext指定默认绑定源页面当前模型,沿元素树继承绑定源
Binding把属性与 UI 连接状态持续同步,不是一次请求输出DataContext
属性通知通知某个值已经变化类似事件发布属性与集合
集合通知通知行增删、替换、移动不等同于数据库变更跟踪属性与集合
ICommand执行动作及判断可执行性业务入口加交互条件命令
依赖属性支持绑定、样式、动画等属性系统不等于依赖注入属性与事件
资源与 Style复用值和外观规则公共配置与主题资源样式
DataTemplate决定数据项如何显示数据的呈现模板模板
ControlTemplate改变控件内部视觉结构控件实现外观模板
Dispatcher调度 UI 线程操作UI 对象具有线程归属异步线程
Host 与 DI组织服务、配置与生命周期熟悉的容器,作用域要显式设计依赖注入

绑定写法​

下面 XAML 是独立属性用法合集。复制到窗口时,需要已经设置 MainViewModel 为 DataContext,并使用其 NewTitle、Todos、SelectedTodo、AddCommand 和 StatusMessage。实际布局仍需容器,见本地 examples/TaskDesk/TaskDesk.Client/MainWindow.xaml。

<TextBox Text="{Binding NewTitle, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="新增" Command="{Binding AddCommand}" />
<DataGrid ItemsSource="{Binding Todos}" SelectedItem="{Binding SelectedTodo, Mode=TwoWay}"
IsReadOnly="True" CanUserAddRows="False" />
<TextBlock Text="{Binding StatusMessage}" TextWrapping="Wrap" />

Mode=TwoWay 表示目标变化也写回源,UpdateSourceTrigger 表示何时写回,这是两个不同维度。TextBox.Text 的默认行为不等于所有属性的默认行为。Binding 是路径解析:路径写错通常产生运行时调试信息,不一定阻止构建。

通知与源生成​

要做的事正确机制注意
改一个文本属性INotifyPropertyChanged 或 ObservableObjectUI 绑定公开属性
增加或删除行ObservableCollection<T>修改发生在 UI 线程
修改普通行属性行对象自己发送通知集合不会替行属性通知
修改不可变 DTO替换集合中的 DTO同时处理所选对象引用
更新按钮状态CanExecuteChanged属性变化不会自动推导所有命令
Toolkit 字段生成ObservableProperty + partial 类newTitle 生成 NewTitle
Toolkit 异步命令RelayCommand + 返回 TaskRefreshAsync 生成 RefreshCommand

TaskDesk 命令条件​

命令可执行条件何时通知
RefreshCommand未忙碌IsBusy 变化
AddCommand未忙碌,标题去空格后非空且不超过 120NewTitle 或 IsBusy 变化
CompleteCommand未忙碌,所选任务未完成SelectedTodo 或 IsBusy 变化
DeleteCommand未忙碌,存在选中项SelectedTodo 或 IsBusy 变化
CancelCommand忙碌IsBusy 变化

门禁应同时出现在可执行性与操作入口,恢复放进 finally。命令 token 经服务传入 HTTP;UI 不调用同步等待。取消与超时后先确认写操作是否已在服务端发生。

生命周期与 HTTP​

WPF 主窗口通常比 HTTP 请求活得更久。桌面 DI 没有自动请求作用域,弹窗或编辑会话需要自行创建、结束 scope。App 使用容器创建窗口时,应移除 StartupUri;配置要复制到输出目录。

HTTP 地址与 JSON 字段属于契约;400 是输入不合法,404 是资源不存在,401/403 涉及身份和授权。HttpClient 的 I/O 直接 await。任务取消不等于事务回滚;客户端隐藏按钮也不等于服务端授权。

Prism 9 速查​

下表对应 Prism.DryIoc 9.0.537 和本地 examples/PrismStudy。不要用旧版命名空间替换表中的 API。

需求API 与命名空间本站说明
组合应用PrismApplication:Prism.DryIoc启动与容器
注册与解析IContainerRegistry、IContainerProvider:Prism.Ioc页面、服务、对话框分别注册
自动配对 ViewModelViewModelLocator:Prism.Mvvm按约定命名或显式映射
属性通知BindableBase.SetProperty:Prism.MvvmMVVM 与命令
同步/异步命令DelegateCommand、AsyncDelegateCommand:Prism.Commands条件变化后通知可执行性
页面导航IRegionManager、INavigationAware:Prism.Navigation.RegionsRegion 导航
参数与导航结果NavigationParameters、NavigationResult:Prism.Navigation结果看 Success、Exception、Cancelled
未保存确认IConfirmNavigationRequest:Prism.Navigation.Regions所有分支完成一次回调
对话框IDialogService、IDialogAware:Prism.Dialogs对话框,关闭用 DialogCloseListener
页面间通知IEventAggregator、PubSubEvent<T>:Prism.Events事件聚合,规划线程与退订
功能模块IModule、IModuleCatalog:Prism.Modularity模块化,初始化不等于 Region 已就绪

完整操作和验收见 PrismStudy 实战。容器组织对象,Region 组织界面,对话框承载需要返回结果的交互,事件表达已发生的变化;需要等待结果的业务操作仍通过服务方法完成。

常见问题​

把“集合更新”和“行属性更新”混在一起,是通知问题的常见来源。把“异步”和“后台线程”视为同义词,则容易造成 UI 线程错误。先用表格定位责任,再到 FAQ 按步骤验证。

练习与验收​

给定“完成请求失败、按钮一直禁用”,从本页列出三个检查点,并在代码中定位它们。验收答案应包含 finally 恢复忙碌、IsBusy 的命令通知、异常是否被正确处理。再说明“已完成任务的完成按钮禁用”由哪个属性变化驱动。

官方资料​