YoYo.Toolkit
1.0.0
See the version list below for details.
dotnet add package YoYo.Toolkit --version 1.0.0
NuGet\Install-Package YoYo.Toolkit -Version 1.0.0
<PackageReference Include="YoYo.Toolkit" Version="1.0.0" />
<PackageVersion Include="YoYo.Toolkit" Version="1.0.0" />
<PackageReference Include="YoYo.Toolkit" />
paket add YoYo.Toolkit --version 1.0.0
#r "nuget: YoYo.Toolkit, 1.0.0"
#:package YoYo.Toolkit@1.0.0
#addin nuget:?package=YoYo.Toolkit&version=1.0.0
#tool nuget:?package=YoYo.Toolkit&version=1.0.0
YoYo.Toolkit
面向 WPF 桌面应用的轻量工具集,为上位机、工控、仪器等「界面 + 设备通信」类项目准备。
全部基于原生 WPF 实现,除 System.Management 外无第三方依赖;不引入 MVVM 框架,也不强制目录约定,可按需取用其中任意一块。
- 目标框架:
net6.0-windows、net8.0-windows - 平台:
AnyCPU/x64/x86 - 许可证:MIT
特性一览
| 模块 | 命名空间 | 内容 |
|---|---|---|
| 导航 | YoYo.Toolkit.Navigations |
BaseNavigation 页面导航,含进入/离开生命周期钩子与强类型参数 |
| 窗口 | YoYo.Toolkit.Services |
WindowService 多窗口注册、跨线程关闭 |
| 网络 | YoYo.Toolkit.Net.Http、.Pings |
BaseRequest / BaseResponse 请求基类;NetworkPing 连通性检测 |
| 控件 | YoYo.Toolkit.Controls.* |
环形进度、树形下拉、水印输入框、图标选项、描边文字 |
| 附加行为 | YoYo.Toolkit.Input、.Animations |
PasswordHelper 密码绑定;OSKHelper 触摸屏软键盘 |
| 通知 | YoYo.Toolkit.Notifies |
TMessageBox 可换肤消息框 |
| 系统 | YoYo.Toolkit.System、.WinApis |
硬盘序列号、主板 ID、机器名;Kernel32.CopyMemory |
| 加密 | YoYo.Toolkit.CryptoServices |
MD5Helper 摘要;RSAHelper AES/RSA 加解密 |
| 工具 | YoYo.Toolkit.Time、.Images、.Converters |
Unix 时间戳、位图加载、常用值转换器 |
安装
dotnet add package YoYo.Toolkit
或在 PackageReference 中指定版本:
<PackageReference Include="YoYo.Toolkit" Version="1.0.0" />
宿主项目需启用 WPF:
<PropertyGroup>
<UseWPF>true</UseWPF>
</PropertyGroup>
快速开始
1. 页面导航
导航以 IGetService 为底座,视图与 ViewModel 都由外部容器提供,包本身不绑定任何 DI 框架。
public sealed class ShellService : IGetService
{
private readonly IServiceProvider _provider;
private FrameworkElement? _view;
public ShellService(IServiceProvider provider) => _provider = provider;
public object GetService(Type? t) => _provider.GetService(t!)!;
public FrameworkElement? GetView() => _view;
public void SetView(FrameworkElement? view) => _view = view;
}
public sealed class MainNavigation : BaseNavigation
{
public MainNavigation(IGetService service) : base(service) { }
public override string NavigationName => "Main";
public override List<NavigateModel> Navigates { get; } = new()
{
new NavigateModel
{
ViewType = "HomeView",
Type = typeof(HomeView),
VMType = typeof(HomeViewModel),
Name = "首页",
},
new NavigateModel
{
ViewType = "DeviceView",
Type = typeof(DeviceView),
VMType = typeof(DeviceViewModel),
Name = "设备",
},
};
public override void InitView() { }
public override void LogWrite(string? msg) { }
public override void LogWrite(string? msg, Exception? exception) { }
}
页面 ViewModel 实现 INavigateIn / INavigateIn<T> / INavigateOut,即可在切换时收到回调:
public sealed class DeviceViewModel : INavigateIn<string>, INavigateOut
{
public void NavigateIn(string? deviceId) { /* 初始化并加载 deviceId */ }
public void NavigateOut() { /* 停止轮询、释放资源 */ }
}
// 跳转
navigation.GoTo("DeviceView", "SN-0001");
navigation.GoTo("HomeView");
2. HTTP 请求
继承 BaseRequest 描述接口,继承 BaseResponse 描述返回,序列化方式可自行覆盖。
public sealed class LoginRequest : BaseRequest
{
public override string RootUrl => "https://api.example.com";
public override string BusinessUrl => "/api/login";
public override HttpMethodTypes Method => HttpMethodTypes.POST;
public override Type ResponseType => typeof(LoginResponse);
public string User { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public override void SerializeObject()
=> Data = JsonSerializer.Serialize(new { User, Password });
}
public sealed class LoginResponse : BaseResponse
{
public string Token { get; private set; } = string.Empty;
public override void DeserializeObj()
{
using var doc = JsonDocument.Parse(Data);
var root = doc.RootElement;
IsOk = root.GetProperty("code").GetInt32() == 0;
Msg = root.TryGetProperty("msg", out var msg) ? msg.GetString() ?? string.Empty : string.Empty;
if (IsOk && root.TryGetProperty("token", out var token))
Token = token.GetString() ?? string.Empty;
}
}
异步调用(内部使用 BackgroundWorker,回调回到 UI 线程):
var request = new LoginRequest { User = "admin", Password = "123456" };
request.DoServiceAsyncCompleted += response => { /* 处理结果 */ };
request.Error += (message, ex) => { /* 统一错误处理 */ };
request.DoWorkerAsync();
// 同步调用
var syncResponse = request.DoWorkerSync();
支持的请求方式:GET、POST、PUT、DELETE,以及带 Body 的 GetBody。鉴权头可在 SetHeader(HttpClient) 中统一注入;请求前后的等待界面通过重写 ShowProcess() / CloseProcess() 接管,IsShowProcess 控制是否启用。
3. 控件
<Window xmlns:yy="clr-namespace:YoYo.Toolkit.Controls.Text;assembly=YoYo.Toolkit"
xmlns:busy="clr-namespace:YoYo.Toolkit.Controls.BusyIndicators;assembly=YoYo.Toolkit"
xmlns:btn="clr-namespace:YoYo.Toolkit.Controls.Button;assembly=YoYo.Toolkit">
<StackPanel>
<yy:PlaceholderTextBox PlaceHolderText="请输入样本编号" />
<busy:TProgressRing IsActive="True" Width="36" Height="36" />
<btn:IconRadioButton Icon="" Content="运行" GroupName="Mode" />
<yy:OutlineText Text="SYSTEM READY" StrokePosition="Outside" />
</StackPanel>
</Window>
树形下拉要求节点实现 ITreeModel(DisplayName、HasChildren()),选中后可通过 SelectCommand 回传节点:
<combo:TreeComboBox ItemsSource="{Binding Devices}"
IsDorpDown="True"
IsOnlyLastNode="True"
SelectCommand="{Binding SelectDeviceCommand}" />
注意:本包不内置主题资源字典。
TProgressRing、IconRadioButton等通过DefaultStyleKey查找样式的控件,需要在宿主应用中提供Style/ControlTemplate,否则控件不会呈现内容。OutlineText、PlaceholderTextBox以代码绘制为主,可直接使用。
4. 消息框
TMessageBox 不依赖系统 MessageBox,外观由你提供的窗口决定:
// 启动时注册弹窗实现,构造函数须为 (string caption, string msg, MessageLevel level)
TMessageBox.Init(typeof(MyMessageDialog));
var result = TMessageBox.ShowMsg("提示", "确认开始运行?", TMessageBox.MessageLevel.Question);
if (result == TMessageBox.TMessageBoxResult.OK)
{
// ...
}
MyMessageDialog 继承 BaseMessageDialog,在关闭前给 MessageBoxResult 赋值即可。
5. 设备与授权
SystemHelper.Init(); // 读取硬盘序列号、主板 ID、机器名
var diskId = SystemHelper.HardDiskID; // 可用于授权绑定
var boardId = SystemHelper.ServerId;
var machine = SystemHelper.ComputerName;
var reachable = await NetworkPing.PingHost("192.168.1.10") is not null;
var md5 = MD5Helper.Md5("hello");
var cipher = RSAHelper.AESEncrypt("plain-text", "your-key");
加解密示例仅作接口参考。用于生产环境前,请自行确认密钥管理、IV 与填充模式是否符合你的安全要求。
6. 密码框绑定
<PasswordBox input:PasswordHelper.Attach="True"
input:PasswordHelper.Password="{Binding Password, Mode=TwoWay}" />
7. 值转换器
<ResourceDictionary xmlns:conv="clr-namespace:YoYo.Toolkit.Converters;assembly=YoYo.Toolkit">
<conv:BoolToVisibilityConverter x:Key="BoolToVis" />
<conv:BoolToReverseConverter x:Key="BoolReverse" />
<conv:NullToVisibilityConverter x:Key="NullToVis" />
</ResourceDictionary>
项目结构
YoYo.Toolkit/
├─ Animations/ 动画附加属性
├─ Controls/ BusyIndicators、Button、ComboBox、Text
├─ Converters/ Bool / Null 与 Visibility 等转换器
├─ CryptoServices/ MD5、RSA(AES)
├─ Images/ 位图加载扩展
├─ Input/ PasswordBox 绑定、触摸屏软键盘
├─ Interfaces/ 窗口与导航接口
├─ Models/ NavigateModel
├─ Navigations/ BaseNavigation
├─ Net/ HTTP 基类、Ping
├─ Notifies/ TMessageBox
├─ Services/ WindowService
├─ System/ 硬件与机器信息
├─ Time/ Unix 时间戳
└─ WinApis/ kernel32 互操作
示例工程见 YoYo.Toolkit.Sample。
构建与打包
# 构建
dotnet build YoYo.Toolkit/YoYo.Toolkit.csproj -c Release -p:Platform=x64
# 打包
dotnet pack YoYo.Toolkit/YoYo.Toolkit.csproj -c Release -p:Platform=x64 -o artifacts
许可证
MIT © 2025 在梦想路上狂奔的蜗牛
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0-windows7.0 is compatible. net7.0-windows was computed. net8.0-windows was computed. net8.0-windows7.0 is compatible. net9.0-windows was computed. net10.0-windows was computed. |
-
net6.0-windows7.0
- System.Management (>= 9.0.6)
-
net8.0-windows7.0
- System.Management (>= 9.0.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
首个正式版本:导航框架、HTTP 请求基类、WPF 控件集、设备信息与加密工具。