SharpBoxesCore.Wpf
1.1.2
dotnet add package SharpBoxesCore.Wpf --version 1.1.2
NuGet\Install-Package SharpBoxesCore.Wpf -Version 1.1.2
<PackageReference Include="SharpBoxesCore.Wpf" Version="1.1.2" />
<PackageVersion Include="SharpBoxesCore.Wpf" Version="1.1.2" />
<PackageReference Include="SharpBoxesCore.Wpf" />
paket add SharpBoxesCore.Wpf --version 1.1.2
#r "nuget: SharpBoxesCore.Wpf, 1.1.2"
#:package SharpBoxesCore.Wpf@1.1.2
#addin nuget:?package=SharpBoxesCore.Wpf&version=1.1.2
#tool nuget:?package=SharpBoxesCore.Wpf&version=1.1.2
🎯 SharpBoxesCore.Wpf.PropertyGrid
一个功能强大、高度可扩展的 WPF 属性编辑器(PropertyGrid),专为现代 MVVM 应用设计。支持自动 UI 生成、属性分组、描述显示、范围验证、滑块调节、自定义按钮、命令绑定、复合类型嵌套、集合编辑、动态刷新、防抖优化等高级功能,开箱即用,适用于配置面板、调试工具、设计器、参数设置等场景。
✨ 核心特性
功能 | 说明 |
---|---|
🔹 自动属性发现 | 扫描对象的公共可读写属性 |
🔹 属性分组(Category) | 支持 [Category("分组名")] 分类显示 |
🔹 属性排序 | 支持 [PropertyOrder(1)] 自定义排序 |
🔹 描述显示 | 鼠标悬停或聚焦时显示 [Description] 内容 |
🔹 显示名称 | 支持 [DisplayName("别名")] 自定义名称 |
🔹 枚举支持 | 显示 [Description] 文本,支持可空枚举 |
🔹 数值范围验证 | 支持 [Range(0, 100)] 输入限制 |
🔹 滑块调节 | 配合 [ShowSlider] 显示 Slider 控件 |
🔹 自定义按钮 | 支持 [AddButton] 添加操作按钮 |
🔹 命令绑定 | 按钮可绑定 ICommand ,支持参数传递 |
🔹 降级机制 | 命令不存在时 fallback 到 ButtonClicked 事件 |
🔹 折叠面板 | 每个 Category 支持 Expander 折叠/展开 |
🔹 事件回调 | 支持 ButtonClicked 和 PropertyValueChanged 事件 |
🔹 错误提示 | 边框变红,显示错误提示,不更新数据源 |
🔹 文件/文件夹选择 | 支持 [SelectFilePath] / [SelectFolder] 对话框 |
🔹 下拉框编辑 | 支持 [EnumerableProperty] 绑定数据源 |
🔹 复合类型嵌套 | 支持类属性展开为子属性面板 |
🔹 集合编辑 | 支持 List<T> / Dictionary<K,V> 弹窗编辑 |
🔹 动态刷新 | 数据源变化自动更新 UI |
🔹 类型安全 | 编辑时保留原始类型,支持自动解析 |
🔹 防抖机制 | 高频更新时自动合并刷新,提升性能 |
🔹 高度自适应 | 支持滚动条,内容展开自动拉伸 |
🔹 搜索属性字段 | 支持搜索指定名称属性编辑 |
🔹 一键展开、折叠 | 支持一键展开、折叠所有属性 |
🚀 快速开始
1. 安装引用
将 PropertyGrid.xaml
和 PropertyGrid.xaml.cs
添加到你的 WPF 项目中。
2. 在 XAML 中使用
<Window x:Class="YourApp.MainWindow"
xmlns:local="clr-namespace:SharpBoxesCore.Wpf.PropertyGrid"
...>
<Grid>
<local:PropertyGrid x:Name="propertyGrid" Padding="10" />
</Grid>
</Window>
3. 绑定数据对象
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
propertyGrid.SelectedObject = new SampleObject();
// 订阅事件
propertyGrid.ButtonClicked += OnButtonClicked;
propertyGrid.PropertyValueChanged += OnPropertyValueChanged;
}
}
📦 示例:完整数据模型
public class SampleObject : INotifyPropertyChanged
{
[Category("基本信息")]
[DisplayName("姓名")]
[Description("用户的全名")]
[EnumerableProperty("AvaliableNames", true)]
public string Name { get; set; } = "张三";
[Category("数值设置")]
[DisplayName("音量")]
[Description("调节音量大小")]
[Range(0, 100)]
[ShowSlider(10, true)]
public int Volume { get; set; } = 75;
[Category("高级")]
[DisplayName("数据模式")]
public DataMode Mode { get; set; } = DataMode.Development;
[Category("文件")]
[DisplayName("配置文件")]
[SelectFilePath(Title = "选择配置文件", Filter = "JSON Files|*.json")]
public string ConfigFile { get; set; } = "";
[Category("路径")]
[DisplayName("工作目录")]
[SelectFolder(Title = "选择工作目录")]
public string WorkDir { get; set; } = "";
[Category("集合")]
public List<string> Hobbies { get; set; } = new() { "阅读", "音乐" };
[Category("字典")]
public Dictionary<string, int> Scores { get; set; } = new()
{
["数学"] = 90,
["英语"] = 85
};
[Category("嵌套对象")]
public Address HomeAddress { get; set; } = new();
[Category("操作")]
[AddButton("ResetCommand", "重置")]
[AddButton("LogCommand", "记录当前值")]
public int RetryCount { get; set; } = 3;
// 命令定义
public ICommand ResetCommand => new RelayCommand<string>(_ => RetryCount = 0);
public ICommand LogCommand => new RelayCommand<string>(action =>
Debug.WriteLine($"日志: {action}, Count={RetryCount}"));
// 下拉数据源
public ObservableCollection<string> AvaliableNames { get; } =
new() { "Alice", "Bob", "Charlie" };
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
🎨 UI 效果预览
(建议补充实际截图)
- 分组折叠/展开
- 滑块与文本框联动
- 按钮自动布局
- 错误输入红色提示
- 描述信息实时显示
- 复合对象嵌套展开
- 集合点击“编辑...”弹窗
- 滚动条支持长内容
🔧 高级功能详解
1. 枚举显示 [Description]
public enum DataMode
{
[Description("开发模式")]
Development,
[Description("生产模式")]
Production
}
✅ 显示为“开发模式”而非 Development
2. 滑块调节 [ShowSlider]
[Range(0, 100)]
[ShowSlider(5, true)]
public int Brightness { get; set; }
✅ 自动生成 Slider + TextBox
联动控件
3. 自定义按钮与命令绑定
[AddButton("SaveCommand", "保存", "另存为")]
[AddButton("DeleteCommand", "删除")]
public string FileName { get; set; }
- ✅ 存在命令 → 绑定执行
- ❌ 不存在 → 触发
ButtonClicked
事件
propertyGrid.ButtonClicked += (s, e) =>
{
MessageBox.Show($"按钮点击: {e.PropertyName} - {e.ButtonText}");
};
4. 数值范围验证
[Range(1, 1000)]
public int Count { get; set; }
✅ 输入非法时:
- 边框变红
- 显示错误提示
- 不更新数据源
5. 下拉框 [EnumerableProperty]
[EnumerableProperty("AvaliableNames", true)]
public string Theme { get; set; }
✅ 显示下拉框,支持自定义输入,数据源动态刷新
6. 文件/文件夹选择
[SelectFilePath(Title = "选择日志")]
public string LogFile { get; set; }
[SelectFolder]
public string BackupDir { get; set; }
✅ 使用 Ookii.Dialogs.Wpf
提供专业对话框
7. 复合类型(嵌套对象)
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
[DisplayName("家庭地址")]
public Address HomeAddress { get; set; }
✅ 自动展开为子属性面板,支持 INotifyPropertyChanged
动态刷新
8. 集合编辑(List / Dictionary)
public List<string> Hobbies { get; set; }
public Dictionary<string, int> Scores { get; set; }
✅ 点击“编辑...”弹出 ListEditor
/ DictEditor
,支持类型保留编辑
🧩 事件系统
PropertyValueChanged
— 属性更改事件
propertyGrid.PropertyValueChanged += (s, e) =>
{
Console.WriteLine($"属性更改: {e.PropertyName}");
Console.WriteLine($" 类型: {e.PropertyType.Name}");
Console.WriteLine($" 旧值: {e.OldValue}");
Console.WriteLine($" 新值: {e.NewValue}");
};
✅ 所有编辑操作(包括集合、文件选择)均触发此事件
ButtonClicked
— 按钮点击事件(fallback)
propertyGrid.ButtonClicked += (s, e) =>
{
if (e.ButtonText == "重置") ResetLogic();
};
✅ 用于未绑定 ICommand
的按钮
🛠️ 自定义 Attribute 说明
Attribute | 用途 | 示例 |
---|---|---|
[Category("分组")] |
属性分组 | Category("网络") |
[DisplayName("别名")] |
自定义显示名 | DisplayName("IP地址") |
[Description("说明")] |
描述信息 | Description("服务器IP") |
[PropertyOrder(1)] |
排序优先级 | 数字越小越靠前 |
[Range(0,100)] |
数值范围 | 支持 int/double/float |
[ShowSlider(10)] |
显示滑块 | TickFrequency=10 |
[AddButton("Cmd", "按钮")] |
添加操作按钮 | 支持多标签 |
[EnumerableProperty("Source", true)] |
下拉框 | 绑定数据源 |
[SelectFilePath] |
文件选择 | 打开 OpenFileDialog |
[SelectFolder] |
文件夹选择 | 打开 FolderBrowserDialog |
⚙️ 高级配置
防抖机制(Debounce)
默认启用,防止高频刷新:
propertyGrid.DebounceEnabled = true; // 默认 true
可调整延迟时间(内部使用 DispatcherTimer
)
手动触发属性更改
propertyGrid.RaisePropertyValueChanged("Name", "旧值", "新值");
用于代码修改属性后通知外部系统
📚 已知限制
限制 | 说明 |
---|---|
❌ 不支持集合增删项 | ListEditor 仅支持修改值 |
❌ 不支持复杂对象列表编辑 | 仅支持简单类型列表 |
❌ 不支持 DateTime 专用控件 |
可用 TextBox 输入 |
✅ 后续计划支持:
DatePicker
、ColorPicker
、IEditableObject
撤销
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. net9.0-windows was computed. net10.0-windows was computed. |
.NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- CommunityToolkit.Mvvm (>= 8.4.0)
- Microsoft.Xaml.Behaviors.Wpf (>= 1.1.135)
- Ookii.Dialogs.Wpf (>= 5.0.1)
-
net6.0-windows7.0
- CommunityToolkit.Mvvm (>= 8.4.0)
- Microsoft.Xaml.Behaviors.Wpf (>= 1.1.135)
- Ookii.Dialogs.Wpf (>= 5.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.