WPF应用程序开发简易模板
1. 说明
本模板是提供wpf应用程序需要快速开发者,可以直接下载模板的安装包即可,创建自己的应用程序,但是只是提供一些demo及样式,需要自己根据实际业务开发逻辑,特别说明本模板不包含数据库方面的应用。
面向二次开发的简易说明:讲清楚目录怎么分、依赖怎么注入、页面怎么加、常见能力怎么用。
1. 项目定位
本仓库是 .NET 8 + WPF 桌面端模板,目标不是做一个业务系统,而是提供可复用的壳:
- MVVM 页面结构
- 依赖注入(DI)
- 对话框 / 消息框
- 主题、多语言、操作日志
- 一组可拷贝的控件与交互示例(分页、表单、联动下拉等)
技术栈要点:CommunityToolkit.Mvvm、Microsoft.Extensions.DependencyInjection、MahApps.Metro、WPFLocalizeExtension、Castle.DynamicProxy。
2. 总体架构
App 启动
├─ 配置 DI(Services / Views)
├─ 初始化语言、主题、操作日志
└─ 解析并显示 MainView
│
▼
View (XAML) ←绑定→ ViewModel ←注入→ Services
│ │
│ ├─ Models(行数据、选项等)
│ └─ 命令 / 状态
└─ Controls / Themes / Resources
核心原则:
| 层 | 职责 | 不该做什么 |
|---|---|---|
| Views | 布局、样式、绑定 | 写业务判断、直接操作文件/串口 |
| ViewModels | 状态、命令、编排服务 | 堆厚重 UI 细节、塞原生控件引用(尽量避免) |
| Services | 可复用能力(窗口、对话框、日志、配置…) | 依赖具体某个页面 XAML |
| Models | 纯数据 / 可观察行模型 | 调用服务 |
| Controls / Themes | 可复用 UI 与样式 | 绑定业务服务 |
3. 目录结构
ChenShiBao.WPF.Template/
├─ App.xaml / App.xaml.cs # 启动、DI 注册
├─ Views/ # 窗口与页面(*View)
├─ ViewModels/ # 对应 *ViewModel;含 DialogViewModel 基类
├─ Models/ # 列表行、选项、节点等
├─ Services/ # 接口 + 实现
├─ Controls/ # 用户控件(分页、搜索框等)
├─ Themes/ # 通用样式资源
├─ Resources/ # Lang.resx / Lang.zh-CN.resx 多语言
├─ Behaviors/ # 附加行为
├─ Helpers/ # 工具类(截图等)
├─ Converters/ # 值转换器
├─ Assets/ # 图标等资源
├─ SystemConfiguration/ # 配置与 JsonLogger 等基础库
└─ appSettings.json # 运行时配置(语言、主题等)
命名约定(很重要):
- 窗口:
XxxView↔XxxViewModel - 对话框服务按约定名反射查找:
ItemEditViewModel→ItemEditView - 不要随意改命名后缀,否则 DI /
DialogService对不上
4. 启动与依赖注入
入口在 App.xaml.cs:
ConfigureServices()注册服务与 ViewApplication_Startup做启动检查与初始化Services.GetRequiredService<MainView>()显示主窗体
4.1 服务生命周期(当前约定)
| 服务 | 生命周期 | 说明 |
|---|---|---|
IDialogService / IMessageBoxService |
Singleton | 全局弹窗 |
ILocalizationService / IThemeService |
Singleton | 语言、主题 |
OperationLogService / ILogService |
Singleton | 日志 |
IConfigService / ISerialPortService |
Singleton | 配置、串口 |
IWindowService |
Transient | 每个窗口自己的实例 |
*View / *ViewModel |
Transient | 按需创建 |
4.2 View ↔ ViewModel 自动装配
RegisterViews 会扫描程序集:同名去掉后缀后配对,并把 ViewModel 设为 DataContext。主窗口还会把 IWindowService.SetWindow(view) 绑到当前窗体。
因此新增页面的最小步骤:
- 新建
Views/FooView.xaml(Window) - 新建
ViewModels/FooViewModel.cs - 需要的服务通过构造函数注入
- 若从主界面打开:用
IDialogService.Show/ShowDialog,或自行GetRequiredService
不必在 App.xaml.cs 里手写每一对注册(扫描会处理符合约定的类型)。
5. MVVM 与命令
- ViewModel 继承
ObservableObject(CommunityToolkit) - 属性:
[ObservableProperty] - 命令:
[RelayCommand] - 对话框基类:
DialogViewModel(提供ConfirmCommand/CancelCommand、DialogResult)
主界面示例集中在 MainView + MainViewModel,用 Tab 分区演示:对话框、下拉/联动、表单、Tab、分页 CRUD、操作日志。
6. 对话框与消息框
消息框
通过 IMessageBoxService:
ShowInformation/ShowWarning/ShowError/ShowSuccessShowConfirmation/ShowQuestion
内部走统一的 CustomMessageBoxView,不要直接 MessageBox.Show(启动失败等极端路径除外)。
业务对话框
- 建
XxxViewModel : DialogViewModel - 建同名
XxxView : Window - 调用:
var vm = new XxxViewModel(...);
if (_dialogService.ShowDialog(vm, vm.Title) == true)
{
// 使用 vm 上的结果字段
}
DialogService 靠命名约定找 View,不依赖 DI 容器里预先登记对话框类型也可以工作(反射创建 Window)。
7. 可复用控件(推荐拷贝方式)
| 控件 / 组件 | 用法摘要 |
|---|---|
PaginationControl + PaginationViewModel |
页面内嵌分页器;TotalCount + PageChanged 后切片或拉数 |
SearchBoxControl |
搜索输入、清空、回车确认 |
Themes/* 样式 |
Button / ComboBox / CheckBox / ToggleSwitch / ScrollBar / Form 等 |
分页列表示例要点(MainViewModel 分页 Tab):
- 全量数据在内存列表,当前页用
DemoPager.Slice(...) - 行模型带
IsSelected,勾选可跨页保留 - 表头全选只作用于当前页
- 增删改后更新
TotalCount并刷新当前页
业务页请先明确:全选是「当前页」还是「全库」,不要无抄示例语义。
8. 主题与多语言
- 主题:
IThemeService,配置键来自appSettings.json(如ThemeKey) - 语言:
ILocalizationService+Resources/Lang*.resx,XAML 用lex:Loc - 代码里读文案:
Lang.Xxx(Lang.Designer.cs)
新增文案时同时改:
Lang.resx(默认/英文侧)Lang.zh-CN.resx- 必要时补
Lang.Designer.cs属性
9. 日志与配置
- 操作日志:
OperationLogService,界面「操作日志」Tab 可查看;落盘目录约定为{根目录}/Logs/ - 配置:
SystemConfiguration+appSettings.json(随输出复制) - 启动时会初始化
AppSettingsHelpers、JsonLogger
改日志根目录、清空日志等能力已在主界面演示,可直接参考 MainViewModel 对应命令。
10. 推荐扩展流程
新增一个业务窗口
Views/OrderListView.xaml+ViewModels/OrderListViewModel.cs- 构造函数注入
IMessageBoxService、IDialogService等 - 从主菜单 / 按钮
ShowDialog打开 - 列表需要分页时:内嵌
PaginationViewModel,UI 放PaginationControl
新增一个编辑弹窗
ItemEditView同款:表单 +SaveCommand/CancelCommand- 校验放在 ViewModel(例如名称非空才允许保存)
- 调用方根据
ShowDialog返回值写回列表
新增样式或控件
- 样式进
Themes/,在App.xaml合并资源字典 - 多页复用再抽
Controls/;只出现一次的交互优先留在页面内,避免过早组件化
11. 明确不做什么(避免踩坑)
- 不要在 View code-behind 堆业务——除非是纯窗口生命周期(如
StateChanged)。 - 不要把演示数据层当持久化——分页 CRUD 示例是内存演示。
- 不要忽略命名约定——View/ViewModel 对不上会导致启动或弹窗失败。
- 不要混用系统 MessageBox 与模板消息框——风格与多语言会不一致。
- MainViewModel 已经偏重——新业务请拆独立 ViewModel,别继续往主 VM 塞。
12. 本地运行
dotnet build ChenShiBao.WPF.Template.csproj
dotnet run --project ChenShiBao.WPF.Template.csproj
要求:已安装 .NET 8 SDK,Windows 环境。
13. 效果演示







14. 使用步骤
以管理员身份打开powershell,重新装这个wpf模板:
14.1 卸载模板
dotnet new uninstall ChenShiBao.WPF.Template

14.2 安装 1.0.4
dotnet new install ChenShiBao.WPF.Template::1.0.4

14.3. 查看是否安装成功
dotnet new list

14.4 vs直接创建项目模板

重新生成运行,效果如下,创建完毕!


浙公网安备 33010602011771号