OpenRobot.Framework.WPFCore
1.1.0
dotnet add package OpenRobot.Framework.WPFCore --version 1.1.0
NuGet\Install-Package OpenRobot.Framework.WPFCore -Version 1.1.0
<PackageReference Include="OpenRobot.Framework.WPFCore" Version="1.1.0" />
<PackageVersion Include="OpenRobot.Framework.WPFCore" Version="1.1.0" />
<PackageReference Include="OpenRobot.Framework.WPFCore" />
paket add OpenRobot.Framework.WPFCore --version 1.1.0
#r "nuget: OpenRobot.Framework.WPFCore, 1.1.0"
#:package OpenRobot.Framework.WPFCore@1.1.0
#addin nuget:?package=OpenRobot.Framework.WPFCore&version=1.1.0
#tool nuget:?package=OpenRobot.Framework.WPFCore&version=1.1.0
OpenRobot.Framework.WPFCore
一个强大的 WPF 桌面应用程序框架库,为 .NET 8.0-windows 应用程序提供依赖注入、AOP、模块化初始化、事件系统、数据分页和现代化启动界面。框架使用 Castle DynamicProxy 实现运行时代理生成和方法拦截,提供企业级的开发体验。
主要特性
1. 依赖注入(DI)
- 基于
Microsoft.Extensions.DependencyInjection的标准 DI 容器 - 支持单例和瞬时服务生命周期
- 使用
SmartValueDependencyAttribute进行自动属性注入 - 完全向后兼容的 API 设计
2. 面向切面编程(AOP)
- 使用 Castle DynamicProxy 实现方法拦截
- 支持异常处理、日志记录、加载指示、通知等切面
- 可组合使用多个 AOP 特性
- 自动处理同步和异步方法
3. 模块化初始化
- 插件式模块加载系统
- 支持生命周期管理(Check、Init、Stop、Exit)
- 可配置模块执行顺序
- 支持重试机制和自定义 UI 交互
4. 事件系统
- 类型安全的事件总线
- 发布/订阅模式
- 支持任意自定义事件类型
- 自动分发事件给所有订阅者
5. 数据分页
- 客户端分页(内存过滤)
- 服务器端分页(通过代理)
- 动态查询构建器(QueryExpression)
- WPF DataGrid 控件集成
6. 界面交互系统
- 对话框管理:支持自定义内容对话框、确认对话框
- 通知系统:支持 Info/Warn/Success/Error 四种级别
- 加载指示:自动显示/隐藏加载状态
- 窗口控制:支持最小化、最大化、移动
7. 现代化启动界面
- SVG Path 图形轮播(默认)
- 支持自定义 App Icon
- 支持自定义轮播图片(PNG/JPG)
- 白色/深色主题支持
- 自动进度显示和错误处理
8. 无需外部资源
- 所有图形元素使用 SVG Path 绘制
- 不依赖 PNG 图片资源
- 减小程序体积
安装
dotnet add package OpenRobot.Framework.WPFCore
或在 Visual Studio 的 NuGet 包管理器控制台中运行:
Install-Package OpenRobot.Framework.WPFCore
快速开始
1. App.xaml 集成
using OpenRobot.Framework;
using OpenRobot.Framework.Startup;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 初始化框架启动窗口
SmartStartupFactory.Init(
"我的应用",
"1.0.0",
imgData: null,
appIcon: null,
carouselImages: null,
colorType: ColorType.White
);
// 启动主窗口
SmartStartupFactory.StartUp(
typeof(MainWindow),
() =>
{
// 启动成功后的回调
Console.WriteLine("应用启动成功");
},
"",
true
);
}
}
2. 应用启动(主窗口)
using OpenRobot.Framework;
using OpenRobot.Framework.Startup;
// 基础启动(使用默认 SVG 轮播)
SmartStartupFactory.Init("我的应用", "1.0.0", null);
SmartStartupFactory.StartUp(typeof(MainWindow), () => { }, "", true);
2. 完整配置启动(白色主题)
// 加载自定义图片资源
var appIcon = File.ReadAllBytes("app-icon.png");
var carouselImages = new List<byte[]>
{
File.ReadAllBytes("slide1.png"),
File.ReadAllBytes("slide2.png")
};
SmartStartupFactory.Init(
"我的应用",
"1.0.0",
imgData: null, // 背景图片(可选)
appIcon: appIcon, // App 图标(可选)
carouselImages: carouselImages, // 轮播图片(可选)
colorType: ColorType.White // 颜色主题:White 或 Dark
);
SmartStartupFactory.StartUp(typeof(MainWindow), () =>
{
// 启动成功后的回调
}, "", true);
使用示例
依赖注入
using OpenRobot.Framework;
using OpenRobot.Framework.Dependency;
// 注册服务
SmartConfiguration.RegisterConfiguration(new MyLogService(), typeof(ISmartLogRegister));
// 获取服务
var logService = SmartConfiguration.GetOrCreate<ISmartLogRegister>();
logService?.Log(SmartLevelEnum.Info, "应用启动成功", SmartLogTagEnum.Host);
创建带 DI 的服务类
// 需要 AOP 拦截的服务
public class MyService : ISmartDependency
{
[SmartValueDependency]
protected ISmartLogRegister ISmartLog { get; set; } = null!;
[SmartException(FriendlyMessage = "操作失败")]
[SmartLog(Message = "执行业务逻辑")]
[SmartLoading(Message = "正在处理...")]
public void DoWork()
{
// 业务逻辑代码
// 异常自动被捕获并显示友好消息
// 日志自动记录
// 加载状态自动显示
}
}
创建模块初始化组件
using OpenRobot.Framework.Dependency;
[SmartModuleInit]
public class DatabaseModuleInit : ISmartModuleInit
{
public int Index => 100;
public int SleepTime => 2000;
public string Title => "数据库初始化";
public event Action<string> PushNoticeMessageEvent;
public void Init()
{
// 一次性初始化逻辑
}
public ModuleCheckResult Check()
{
// 重复检查直到成功
return new ModuleCheckResult { Success = true };
}
public void Stop() { }
public void Exit() { }
}
事件系统
// 定义事件数据
public class UserLoginEvent : SmartEventData
{
public string UserId { get; set; }
public DateTime LoginTime { get; set; }
}
// 订阅事件
public class LoginEventHandler : ISmartEventRegister<UserLoginEvent>
{
public Task EventRefresh(UserLoginEvent data)
{
Console.WriteLine($"用户 {data.UserId} 登录于 {data.LoginTime}");
return Task.CompletedTask;
}
}
// 触发事件
var eventHandler = SmartConfiguration.GetOrCreate<ISmartEventHander>();
eventHandler?.Trigger(new UserLoginEvent { UserId = "user123", LoginTime = DateTime.Now });
数据分页
using OpenRobot.Framework.DataPgination;
// 客户端分页
var pagination = new PaginationClient<UserDto>(allUsers);
pagination.PageIndexChanged += (sender, e) => Console.WriteLine($"当前页: {e.NewPageIndex}");
// 服务器端分页
var serverPagination = new PagintionServer<UserDto>(proxy);
await serverPagination.RefreshData();
创建带 DI 的 ViewModel
public class MyViewModel : ISmartAutoDependency
{
[SmartValueDependency]
protected ISmartDialogRegister ISmartDialog { get; set; } = null!;
[SmartValueDependency]
protected ISmartLoadingRegister ISmartLoading { get; set; } = null!;
public async Task SaveData()
{
ISmartLoading?.SetBusy("正在保存...");
try
{
// 保存逻辑
await ISmartDialog?.Success("成功", "数据已保存");
}
finally
{
ISmartLoading?.ClearBusy();
}
}
}
MainWindow 集成
完整集成 MainWindow 到框架:
using OpenRobot.Framework;
using OpenRobot.Framework.Dependency;
public partial class MainWindow : Window,
ISmartLoadingRegister, // 加载指示器
ISmartNoticeRegister, // 通知消息
ISmartDialogRegister, // 对话框管理
ISoftwareViewSizeChange // 窗口大小控制
{
public MainWindow()
{
InitializeComponent();
InitializeSmartConfiguration();
StateChanged += MainWindow_StateChanged;
}
private void InitializeSmartConfiguration()
{
// 注册窗口服务到框架容器
SmartConfiguration.RegisterConfiguration(this, typeof(ISmartLoadingRegister));
SmartConfiguration.RegisterConfiguration(this, typeof(ISmartNoticeRegister));
SmartConfiguration.RegisterConfiguration(this, typeof(ISmartDialogRegister));
SmartConfiguration.RegisterConfiguration(this, typeof(ISoftwareViewSizeChange));
}
// ISmartNoticeRegister 实现
public void Notice(SmartLevelEnum smartState, string message)
{
if (Dispatcher.CheckAccess())
{
userNotice?.Notice(smartState, message);
}
else
{
Dispatcher.Invoke(() => userNotice?.Notice(smartState, message));
}
}
// ISmartLoadingRegister 实现
public void SetBusy(string message = "")
{
if (Dispatcher.CheckAccess())
{
userLoading?.SetBusy(message);
}
else
{
Dispatcher.Invoke(() => userLoading?.SetBusy(message));
}
}
public void ClearBusy()
{
if (Dispatcher.CheckAccess())
{
userLoading?.ClearBusy();
}
else
{
Dispatcher.Invoke(() => userLoading?.ClearBusy());
}
}
// ISmartDialogRegister 实现
public void Modal(string title, FrameworkElement context)
{
if (Dispatcher.CheckAccess())
{
var dialogControl = new DialogCustomControl();
(context as ISmartElementCloseEvent)!.SendCloseEvent += (s) =>
{
dialogMaskPanel.Visibility = Visibility.Collapsed;
dialogPanel.Children.Remove(dialogControl);
};
dialogMaskPanel.Visibility = Visibility.Visible;
dialogPanel.Children.Add(dialogControl);
dialogControl.Modal(title, context);
}
else
{
Dispatcher.Invoke(() => Modal(title, context));
}
}
// ISoftwareViewSizeChange 实现
public void Maximize()
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
}
public void Minimize()
{
if (WindowState == WindowState.Minimized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Minimized;
}
public void Moved() { }
}
MainWindow XAML 结构
<Window x:Class="YourApp.MainWindow"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent">
<Border Background="White">
<Grid>
<DockPanel x:Name="mainControl" LastChildFill="True" />
<Grid x:Name="dialogMaskPanel" Visibility="Collapsed">
<Grid.Background>
<SolidColorBrush Color="Black" Opacity="0.3"/>
</Grid.Background>
<DockPanel x:Name="dialogPanel" LastChildFill="True" />
</Grid>
<DockPanel x:Name="loadingPanel" LastChildFill="True">
<local:LoadingControl x:Name="userLoading" />
</DockPanel>
<DockPanel x:Name="noticePanel" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<local:NoticeControl x:Name="userNotice" Margin="0,0,20,20" />
</DockPanel>
</Grid>
</Border>
</Window>
对话框服务
框架提供完整的对话框管理功能,支持自定义内容和确认对话框。
对话框类型
- 自定义内容对话框 - 显示任意 FrameworkElement 作为对话框内容
- 确认对话框 - 显示简单文本消息的确认对话框
CustomFooterConfig 配置
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
PrimaryText |
string |
"确定" | 主按钮文本 |
CancelText |
string |
"取消" | 取消按钮文本 |
FooterType |
DialogFooterType |
PrimaryAndCancel |
页脚类型 |
Size |
DialogSize |
800x600 | 对话框尺寸 |
OkAction |
Func<Task<bool>> |
null |
主按钮回调(返回 true 关闭) |
CancelAction |
Action |
null |
取消按钮回调 |
对话框示例
public class MyViewModel : ISmartAutoDependency
{
[SmartValueDependency]
protected ISmartDialogRegister ISmartDialog { get; set; } = null!;
public async Task ShowCustomDialog()
{
var content = new MyCustomControl();
var config = new CustomFooterConfig
{
PrimaryText = "保存",
CancelText = "放弃",
FooterType = DialogFooterType.PrimaryAndCancel,
Size = new DialogSize { Width = 600, Height = 400 },
OkAction = async () =>
{
// 保存逻辑
return true;
}
};
ISmartDialog.Modal("编辑用户", content, config);
}
public async Task ShowConfirmDialog()
{
ISmartDialog.ModalConfirm("确认删除", "确定要删除这条记录吗?", async () =>
{
// 删除逻辑
await DeleteRecord();
return true;
});
}
}
自定义控件关闭事件
public partial class MyCustomControl : UserControl, ISmartElementCloseEvent
{
public event Action<FrameworkElement> SendCloseEvent;
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
// 触发关闭事件,通知 MainWindow 移除对话框
SendCloseEvent?.Invoke(this);
}
}
AOP 特性
框架提供以下 AOP 拦截器,通过特性标记即可使用:
| 特性 | 说明 | 接口 |
|---|---|---|
[SmartException] |
捕获异常并显示友好消息 | ISmartExceptionRegister |
[SmartLog] |
记录方法调用日志 | ISmartLogRegister |
[SmartLoading] |
显示加载指示器 | ISmartLoadingRegister |
[SmartNotice] |
发送通知消息 | ISmartNoticeRegister |
AOP 特性参数
[SmartException(
FriendlyMessage = "操作失败,请重试", // 自定义错误消息
IsExit = false, // 是否在异常时退出
NextExecute = false // 是否在异常后继续执行
)]
public void DoWork() { }
[SmartLog(
Message = "执行业务逻辑", // 自定义日志消息
Tag = SmartLogTagEnum.Host // 日志标签
)]
public void ProcessData() { }
[SmartLoading(Message = "正在加载...")]
public async Task LoadData() { }
[SmartNotice(Message = "操作已完成")]
public void CompleteTask() { }
启动界面
默认轮播内容
框架提供两个默认的 SVG Path 轮播内容:
- 框架架构图 - 展示 WPF Core 的核心架构(DI、AOP、Event、Pager)
- 功能特性 - 展示框架的 5 大核心功能
自定义轮播图片
// 支持传入自定义图片(PNG/JPG)
var carouselImages = new List<byte[]>
{
File.ReadAllBytes("feature1.png"),
File.ReadAllBytes("feature2.png"),
File.ReadAllBytes("feature3.png")
};
SmartStartupFactory.Init(
appName,
version,
carouselImages: carouselImages
);
启动窗口布局
- 左上角:App Icon + 应用名称
- 右上方:版本号
- 中间:轮播区域(图片或 SVG Path)
- 下方:进度条 + 百分比 + 消息提示
- 底部:状态信息
核心接口
| 接口 | 命名空间 | 说明 |
|---|---|---|
ISmartDependency |
OpenRobot.Framework.Dependency |
需要代理的 DI 服务 |
ISmartAutoDependency |
OpenRobot.Framework.Dependency |
ViewModel(无代理) |
ISmartModuleInit |
OpenRobot.Framework.Dependency |
模块初始化接口 |
ISmartEventRegister<T> |
OpenRobot.Framework.Core |
事件订阅者 |
ISmartEventHander |
OpenRobot.Framework.Core |
事件触发器 |
IPagination<T> |
OpenRobot.Framework.DataPgination |
分页接口 |
ISmartDialogRegister |
OpenRobot.Framework.Dependency |
对话框管理 |
ISmartNoticeRegister |
OpenRobot.Framework.Dependency |
通知消息 |
ISmartLoadingRegister |
OpenRobot.Framework.Dependency |
加载指示器 |
ISoftwareViewSizeChange |
OpenRobot.Framework.WPFCore.Dependency |
窗口大小控制 |
ISmartElementCloseEvent |
OpenRobot.Framework.Dependency |
元素关闭事件 |
枚举类型
| 枚举 | 命名空间 | 说明 |
|---|---|---|
SmartLevelEnum |
OpenRobot.Framework |
通知/日志级别(Info/Warn/Success/Error) |
DialogFooterType |
OpenRobot.Framework.Dependency |
对话框页脚类型(PrimaryAndCancel/Primary/Cancel) |
SmartLogTagEnum |
OpenRobot.Framework |
日志标签(Host/Api) |
ColorType |
OpenRobot.Framework.Startup |
启动窗口颜色主题(White/Dark) |
配置选项
SmartConfiguration 方法
| 方法 | 说明 | 示例 |
|---|---|---|
RegisterConfiguration(object) |
注册单例服务 | SmartConfiguration.RegisterConfiguration(service) |
RegisterConfiguration(object, Type) |
使用接口注册 | SmartConfiguration.RegisterConfiguration(impl, typeof(IService)) |
GetOrCreate<T>() |
获取或创建服务 | SmartConfiguration.GetOrCreate<IService>() |
Get<T>(string) |
获取指定服务 | SmartConfiguration.Get<IService>("fullName") |
GetAll<T>() |
获取所有指定类型的服务 | SmartConfiguration.GetAll<IService>() |
SmartStartupFactory.Init 参数
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
appName |
string |
应用程序名称 | 必填 |
version |
string |
版本号 | 必填 |
imgData |
byte[] |
背景图片数据 | null |
appIcon |
byte[] |
App Icon 图片数据 | null |
carouselImages |
List<byte[]> |
轮播图片列表 | null |
colorType |
ColorType |
颜色主题(White/Dark) | ColorType.White |
SmartStartupFactory.StartUp 参数
| 参数 | 类型 | 说明 |
|---|---|---|
mainWindowType |
Type |
主窗口类型 |
successAction |
Action |
启动成功回调 |
errorMessage |
string |
错误消息 |
isShowError |
bool |
是否显示错误界面 |
依赖项
| 包名 | 版本 | 用途 |
|---|---|---|
| Castle.Core | 5.1.1 | 动态代理 |
| Castle.Core.AsyncInterceptor | 2.1.0 | 异步拦截 |
| Microsoft.Extensions.DependencyInjection | 8.0.0 | 依赖注入 |
系统要求
- .NET 8.0-windows 或更高版本
- Windows 操作系统
最佳实践
1. 服务生命周期选择
// 单例服务 - 用于无状态服务(推荐)
SmartConfiguration.RegisterConfiguration(new MyService(), typeof(IService));
// 瞬时服务 - 通过工厂方法创建
var instance = ProxyContainerFactory.Build<MyService>();
2. 线程安全
所有 UI 更新操作都应该检查 Dispatcher:
public void Notice(SmartLevelEnum smartState, string message)
{
if (Dispatcher.CheckAccess())
{
// UI 线程,直接更新
userNotice?.Notice(smartState, message);
}
else
{
// 非 UI 线程,使用 Dispatcher
Dispatcher.Invoke(() => userNotice?.Notice(smartState, message));
}
}
3. 异步方法使用 AOP
// 正确:异步方法使用 async/await
[SmartLoading(Message = "正在加载...")]
public async Task LoadData()
{
await Task.Delay(1000);
}
// 错误:不要在异步方法中使用 .Result 或 .Wait()
[SmartLoading]
public void LoadData() // 应该是 async Task
{
var result = SomeAsyncMethod().Result; // 可能死锁
}
4. 自定义控件关闭事件
自定义控件应该实现 ISmartElementCloseEvent 接口:
public partial class MyCustomControl : UserControl, ISmartElementCloseEvent
{
public event Action<FrameworkElement> SendCloseEvent;
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
// 触发关闭事件
SendCloseEvent?.Invoke(this);
}
}
5. 模块初始化顺序
使用 Index 属性控制模块初始化顺序:
[SmartModuleInit]
public class DatabaseModuleInit : ISmartModuleInit
{
public int Index => 10; // 最先执行
public void Init() { }
}
[SmartModuleInit]
public class UIModuleInit : ISmartModuleInit
{
public int Index => 100; // 后执行
public void Init() { }
}
项目结构
OpenRobot.Framework.WPFCore/
├── Core/ # 核心组件
│ ├── Element/ # UI 元素控件基类
│ └── Factory/ # 创建控件和事件的工厂类
├── DataPagination/ # 数据分页
│ ├── Controls/ # WPF 分页控件
│ ├── Core/ # 分页接口和实现
│ └── Model/ # 分页数据模型
├── Dependency/ # 依赖注入系统
│ ├── Attributes/ # DI 和 AOP 特性
│ └── Core/ # 核心 DI 接口
│ ├── ISmartDialogRegister.cs # 对话框注册接口
│ ├── ISmartNoticeRegister.cs # 通知注册接口
│ ├── ISmartLoadingRegister.cs # 加载注册接口
│ ├── ISmartLogRegister.cs # 日志注册接口
│ └── ISmartExceptionRegister.cs # 异常注册接口
├── EmitProxy/ # AOP 拦截器实现
│ ├── Core/ # 拦截器基类
│ └── Sync/ # 同步方法拦截器
├── Model/ # 框架数据模型
│ ├── SmartLevelEnum.cs # 通知/日志级别枚举
│ └── ...
├── Startup/ # 应用程序启动基础设施
│ ├── Core/ # 启动工厂和初始化
│ ├── LaunchWindow.xaml # 主启动窗口(SVG Path 轮播)
│ ├── LaunchCustomWindow.xaml # 自定义启动窗口
│ └── LaunchExitControl.xaml # 错误退出控制
├── SmartConfiguration.cs # 中央配置注册表(Microsoft.Extensions.DependencyInjection)
├── FrameWorkWPFCoreInit.cs # 框架模块初始化
├── CLAUDE.md # Claude Code 工作指导
├── README.md # 项目文档
└── OpenRobot.Framework.WPFCore.csproj # 项目文件
常见问题
Q: 如何让 AOP 拦截器生效?
A: 确保类实现 ISmartDependency 接口并通过框架创建实例:
// 通过框架创建(会应用 AOP)
var service = ProxyContainerFactory.Build<MyService>();
// 或者通过 DI 自动注入
public class MyClass : ISmartAutoDependency
{
[SmartValueDependency]
protected MyService MyService { get; set; } = null!;
}
Q: 对话框关闭事件不触发?
A: 自定义控件需要实现 ISmartElementCloseEvent 接口:
public partial class MyControl : UserControl, ISmartElementCloseEvent
{
public event Action<FrameworkElement> SendCloseEvent;
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
SendCloseEvent?.Invoke(this);
}
}
Q: 如何实现线程安全的 UI 更新?
A: 使用 Dispatcher.CheckAccess() 检查当前线程:
public void Notice(SmartLevelEnum smartState, string message)
{
if (Dispatcher.CheckAccess())
{
// UI 线程,直接更新
userNotice?.Notice(smartState, message);
}
else
{
// 非 UI 线程,使用 Dispatcher
Dispatcher.Invoke(() => userNotice?.Notice(smartState, message));
}
}
Q: 模块初始化不执行?
A: 确保类标记了 [SmartModuleInit] 特性:
[SmartModuleInit] // 必须添加此特性
public class MyModuleInit : ISmartModuleInit
{
public int Index => 100;
// ...
}
Q: 事件订阅不工作?
A: 确保事件订阅者注册到框架容器:
// 在模块初始化或启动时注册
SmartConfiguration.RegisterConfiguration(new MyEventHandler());
Q: 如何自定义启动窗口颜色主题?
A: 使用 ColorType 参数:
SmartStartupFactory.Init(
"我的应用",
"1.0.0",
colorType: ColorType.Dark // 或 ColorType.White
);
许可证
本项目采用 MIT 许可证。
作者
OpenRobot
反馈与贡献
欢迎通过以下方式提供反馈:
- 提交 Issue
- 发起 Pull Request
- 联系维护者
提示: 本框架专为 WPF 桌面应用程序设计,提供了完整的开发基础设施,大幅提升开发效率。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-windows7.0 is compatible. net9.0-windows was computed. net10.0-windows was computed. |
-
net8.0-windows7.0
- Castle.Core (>= 5.1.1)
- Castle.Core.AsyncInterceptor (>= 2.1.0)
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.