WPF应用程序开发简易模板

1. 说明

本模板是提供wpf应用程序需要快速开发者,可以直接下载模板的安装包即可,创建自己的应用程序,但是只是提供一些demo及样式,需要自己根据实际业务开发逻辑,特别说明本模板不包含数据库方面的应用。

面向二次开发的简易说明:讲清楚目录怎么分、依赖怎么注入、页面怎么加、常见能力怎么用。

1. 项目定位

本仓库是 .NET 8 + WPF 桌面端模板,目标不是做一个业务系统,而是提供可复用的壳:

  • MVVM 页面结构
  • 依赖注入(DI)
  • 对话框 / 消息框
  • 主题、多语言、操作日志
  • 一组可拷贝的控件与交互示例(分页、表单、联动下拉等)

技术栈要点:CommunityToolkit.MvvmMicrosoft.Extensions.DependencyInjectionMahApps.MetroWPFLocalizeExtensionCastle.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           # 运行时配置(语言、主题等)

命名约定(很重要):

  • 窗口:XxxViewXxxViewModel
  • 对话框服务按约定名反射查找:ItemEditViewModelItemEditView
  • 不要随意改命名后缀,否则 DI / DialogService 对不上

4. 启动与依赖注入

入口在 App.xaml.cs

  1. ConfigureServices() 注册服务与 View
  2. Application_Startup 做启动检查与初始化
  3. 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) 绑到当前窗体。

因此新增页面的最小步骤:

  1. 新建 Views/FooView.xamlWindow
  2. 新建 ViewModels/FooViewModel.cs
  3. 需要的服务通过构造函数注入
  4. 若从主界面打开:用 IDialogService.Show / ShowDialog,或自行 GetRequiredService

不必在 App.xaml.cs 里手写每一对注册(扫描会处理符合约定的类型)。

5. MVVM 与命令

  • ViewModel 继承 ObservableObject(CommunityToolkit)
  • 属性:[ObservableProperty]
  • 命令:[RelayCommand]
  • 对话框基类:DialogViewModel(提供 ConfirmCommand / CancelCommandDialogResult

主界面示例集中在 MainView + MainViewModel,用 Tab 分区演示:对话框、下拉/联动、表单、Tab、分页 CRUD、操作日志。

6. 对话框与消息框

消息框

通过 IMessageBoxService

  • ShowInformation / ShowWarning / ShowError / ShowSuccess
  • ShowConfirmation / ShowQuestion

内部走统一的 CustomMessageBoxView,不要直接 MessageBox.Show(启动失败等极端路径除外)。

业务对话框

  1. XxxViewModel : DialogViewModel
  2. 建同名 XxxView : Window
  3. 调用:
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.XxxLang.Designer.cs

新增文案时同时改:

  1. Lang.resx(默认/英文侧)
  2. Lang.zh-CN.resx
  3. 必要时补 Lang.Designer.cs 属性

9. 日志与配置

  • 操作日志OperationLogService,界面「操作日志」Tab 可查看;落盘目录约定为 {根目录}/Logs/
  • 配置SystemConfiguration + appSettings.json(随输出复制)
  • 启动时会初始化 AppSettingsHelpersJsonLogger

改日志根目录、清空日志等能力已在主界面演示,可直接参考 MainViewModel 对应命令。

10. 推荐扩展流程

新增一个业务窗口

  1. Views/OrderListView.xaml + ViewModels/OrderListViewModel.cs
  2. 构造函数注入 IMessageBoxServiceIDialogService
  3. 从主菜单 / 按钮 ShowDialog 打开
  4. 列表需要分页时:内嵌 PaginationViewModel,UI 放 PaginationControl

新增一个编辑弹窗

  1. ItemEditView 同款:表单 + SaveCommand / CancelCommand
  2. 校验放在 ViewModel(例如名称非空才允许保存)
  3. 调用方根据 ShowDialog 返回值写回列表

新增样式或控件

  • 样式进 Themes/,在 App.xaml 合并资源字典
  • 多页复用再抽 Controls/;只出现一次的交互优先留在页面内,避免过早组件化

11. 明确不做什么(避免踩坑)

  1. 不要在 View code-behind 堆业务——除非是纯窗口生命周期(如 StateChanged)。
  2. 不要把演示数据层当持久化——分页 CRUD 示例是内存演示。
  3. 不要忽略命名约定——View/ViewModel 对不上会导致启动或弹窗失败。
  4. 不要混用系统 MessageBox 与模板消息框——风格与多语言会不一致。
  5. MainViewModel 已经偏重——新业务请拆独立 ViewModel,别继续往主 VM 塞。

12. 本地运行

dotnet build ChenShiBao.WPF.Template.csproj
dotnet run --project ChenShiBao.WPF.Template.csproj

要求:已安装 .NET 8 SDK,Windows 环境。

13. 效果演示

image

image

image

image

image

image

image

14. 使用步骤

以管理员身份打开powershell,重新装这个wpf模板:

14.1 卸载模板

dotnet new uninstall ChenShiBao.WPF.Template
image

14.2 安装 1.0.4

dotnet new install ChenShiBao.WPF.Template::1.0.4
image

14.3. 查看是否安装成功

dotnet new list
image

14.4 vs直接创建项目模板

image

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

posted @ 2026-08-21 11:40  似梦亦非梦  阅读(6)  评论(0)    收藏  举报