SharpBoxesCore.Wpf
1.1.0
.NET 6.0
This package targets .NET 6.0. The package is compatible with this framework or higher.
.NET Framework 4.8
This package targets .NET Framework 4.8. The package is compatible with this framework or higher.
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package SharpBoxesCore.Wpf --version 1.1.0
NuGet\Install-Package SharpBoxesCore.Wpf -Version 1.1.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SharpBoxesCore.Wpf" Version="1.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SharpBoxesCore.Wpf" Version="1.1.0" />
<PackageReference Include="SharpBoxesCore.Wpf" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SharpBoxesCore.Wpf --version 1.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: SharpBoxesCore.Wpf, 1.1.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SharpBoxesCore.Wpf@1.1.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SharpBoxesCore.Wpf&version=1.1.0
#tool nuget:?package=SharpBoxesCore.Wpf&version=1.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
🎯 SharpBoxesCore.Wpf.PropertyGrid
一个功能强大、高度可扩展的 WPF 属性编辑器(PropertyGrid),专为现代 MVVM 应用设计。支持自动 UI 生成、属性分组、描述显示、范围验证、滑块调节、自定义按钮、命令绑定等高级功能,开箱即用,适用于配置面板、调试工具、设计器等场景。
✨ 核心特性
功能 | 说明 |
---|---|
🔹 自动属性发现 | 自动扫描对象的公共可读写属性 |
🔹 属性分组(Category) | 支持 [Category("分组名")] 分类显示 |
🔹 属性排序 | 支持 [PropertyOrder(1)] 自定义排序 |
🔹 描述显示 | 鼠标悬停或聚焦时显示 [Description] 内容 |
🔹 显示名称 | 支持 [DisplayName("别名")] 自定义名称 |
🔹 枚举支持 | 显示 [Description] 文本,支持可空枚举 |
🔹 数值范围验证 | 支持 [Range(0, 100)] 输入限制 |
🔹 滑块调节 | 配合 [ShowSlider] 显示 Slider 控件 |
🔹 自定义按钮 | 支持 [AddButton] 添加操作按钮 |
🔹 命令绑定 | 按钮可绑定 ICommand ,支持参数传递 |
🔹 降级机制 | 命令不存在时自动 fallback 到事件回调 |
🔹 折叠面板 | 每个 Category 支持 Expander 折叠/展开 |
🔹 事件回调 | 支持 ButtonClicked 事件回调 |
🔹 错误提示 | 边框变红,显示错误提示,不更新数据源 |
🔹 降级机制 | 命令不存在时自动 fallback 到事件回调 |
🔹 选择文件对话框 | 支持 [SelectFilePathAttribute] 打开文件对话框 |
🔹 选择文件夹对话框 | 支持 [SelectFolderAttribute] 打开文件夹对话框 |
🚀 快速开始
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" />
</Grid>
</Window>
3. 绑定数据对象
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
propertyGrid.SelectedObject = new SampleObject();
}
}
📦 示例:完整数据模型
public class SampleObject : INotifyPropertyChanged
{
private string _name = "示例对象";
private int _age = 25;
private double _height = 175.5;
private SampleEnum _category = SampleEnum.选项一;
private Priority _priority = Priority.Normal;
private bool _isActive = true;
private string _description = "这是一个示例对象的描述";
public ICommand OpenFileCommand =>
new RelayCommand<string>(action =>
{
if (action == "浏览...")
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "所有文件|*.*";
if (dialog.ShowDialog() == true)
{
FilePath = dialog.FileName;
}
}
else if (action == "打开文件夹")
{
if (System.IO.File.Exists(FilePath))
{
Process.Start("explorer.exe", Path.GetDirectoryName(FilePath));
}
}
OnPropertyChanged(nameof(FilePath));
});
public ICommand AddNameCommand => new RelayCommand(() =>
{
AvaliableNames.Add($"Item_{AvaliableNames.Count}");
});
[Category("调试")]
[DisplayName("重置计数")]
[Description("点击按钮可重置或刷新计数")]
[AddButton("递增")]
[AddButton("重置")]
[AddButton("AddNameCommand", "日志")] // 多个 [AddButton] 也支持
public int Count { get; set; } = 0;
[Category("文件")]
[DisplayName("路径")]
[AddButton("OpenFileCommand", "浏览...")]
[AddButton("OpenFileCommand", "打开文件夹")]
public string FilePath { get; set; } = "";
[Category("基本信息")]
[Description("对象的名称,用于标识该对象")]
[PropertyOrder(1)]
[DisplayName("名称")]
[EnumerableProperty("AvaliableNames", true)] // 允许自定义
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
[Category("基本信息")]
[Description("对象的年龄,必须为正整数")]
[PropertyOrder(2)]
[DisplayName("年龄")]
public int Age
{
get { return _age; }
set
{
if (_age != value)
{
_age = value;
OnPropertyChanged(nameof(Age));
}
}
}
[Category("基本信息")]
[Description("对象的身高,单位为厘米,支持小数")]
[PropertyOrder(3)]
[DisplayName("身高")]
[Range(100, 400)]
[ShowSlider(10, true)] // 每10一个刻度,吸附
public double Height
{
get { return _height; }
set
{
if (_height != value)
{
_height = value;
OnPropertyChanged(nameof(Height));
}
}
}
[Category("分类设置")]
[Description("对象所属的类别,从预定义的选项中选择")]
[PropertyOrder(1)]
[DisplayName("类别")]
public SampleEnum Category
{
get { return _category; }
set
{
if (_category != value)
{
_category = value;
OnPropertyChanged(nameof(Category));
}
}
}
[Category("分类设置")]
[Description("对象的优先级,影响处理顺序")]
[PropertyOrder(2)]
[DisplayName("优先级")]
public Priority Priority
{
get { return _priority; }
set
{
if (_priority != value)
{
_priority = value;
OnPropertyChanged(nameof(Priority));
}
}
}
[Category("状态控制")]
[Description("标识对象是否处于活动状态")]
[PropertyOrder(1)]
[DisplayName("活动状态")]
public bool IsActive
{
get { return _isActive; }
set
{
if (_isActive != value)
{
_isActive = value;
OnPropertyChanged(nameof(IsActive));
}
}
}
[Category("其他信息")]
[Description("对象的详细描述信息,可以包含多行文本")]
[PropertyOrder(1)]
[DisplayName("描述")]
[EnumerableProperty("AvaliableNames", false)] // 允许自定义
public string Description
{
get { return _description; }
set
{
if (_description != value)
{
_description = value;
OnPropertyChanged(nameof(Description));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName="")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// 数据源(下拉选项)
private ObservableCollection<string> _avaliableNames = new ObservableCollection<string> { "A", "B" };
public ObservableCollection<string> AvaliableNames
{
get => _avaliableNames;
set
{
_avaliableNames = value;
OnPropertyChanged();
}
}
[Category("文件")]
[DisplayName("配置文件")]
[SelectFilePath(Title = "选择配置文件", Filter = "JSON Files|*.json|All Files|*.*")]
public string ConfigFile { get; set; } = "";
[Category("路径")]
[DisplayName("工作目录")]
[SelectFolder]
public string WorkDir { get; set; } = "";
[Category("选项")]
[DisplayName("主题")]
[EnumerableProperty("AvailableThemes", true)]
public string Theme { get; set; } = "Dark";
public List<string> AvailableThemes { get; } = new() { "Light", "Dark", "Blue" };
}
🎨 UI 效果预览
(建议补充一张截图)
- 分组折叠/展开
- 滑块与文本框联动
- 按钮自动布局
- 错误输入红色提示
- 描述信息实时显示
🔧 高级功能详解
1. 枚举显示 [Description]
public enum Quality
{
[Description("高清")]
High,
[Description("标清")]
Medium,
[Description("低清")]
Low
}
✅ 显示为“高清”而非 High
2. 滑块调节 [ShowSlider]
[Range(0, 100)]
[ShowSlider(5, true)] // 每5一格,吸附
public int Brightness { get; set; }
✅ 自动生成 Slider + TextBox
联动控件
3. 自定义按钮与命令绑定
[AddButton("SaveCommand", "保存", "另存为")]
[AddButton("DeleteCommand", "删除")]
public string FileName { get; set; }
public ICommand SaveCommand => new RelayCommand<string>(...);
// DeleteCommand 未定义 → fallback 到事件
✅ 存在命令:绑定执行
❌ 不存在:触发 ButtonClicked
事件
propertyGrid.ButtonClicked += (sender, e) =>
{
MessageBox.Show($"执行: {e.PropertyName} - {e.ButtonText}");
};
4. 数值范围验证
[Range(1, 1000)]
public int Count { get; set; }
✅ 输入非法时:
- 边框变红
- 显示错误提示
- 不更新数据源
🧩 事件与回调
ButtonClicked
事件(fallback 机制)
propertyGrid.ButtonClicked += (sender, e) =>
{
string property = e.PropertyName;
string button = e.ButtonText;
// 统一处理未绑定命令的按钮
switch (property)
{
case "RetryCount":
if (button == "重置") ((SampleObject)propertyGrid.SelectedObject).RetryCount = 0;
break;
}
};
🛠️ 自定义 Attribute 说明
Attribute | 用途 | 示例 |
---|---|---|
[Category("分组")] |
属性分组 | Category("网络") |
[DisplayName("别名")] |
自定义显示名 | DisplayName("IP地址") |
[Description("说明")] |
描述信息 | Description("服务器IP") |
[PropertyOrder(1)] |
排序优先级 | 数字越小越靠前 |
[Range(0,100)] |
数值范围 | 支持 int/double/float |
[ShowSlider(10)] |
显示滑块 | TickFrequency=10 |
[AddButton("Cmd", "按钮1", "按钮2")] |
添加操作按钮 | 支持多标签 |
📚 已知限制
- ❌ 暂不支持
DateTime
专用控件(可用TextBox
)
✅ 后续版本将支持
DatePicker
、ColorPicker
、FilePathEditor[已支持]
、FolderEditor[已支持]
等。
🤝 贡献与反馈
欢迎提交 Issue 或 Pull Request!
项目地址:https://github.com/yourname/sharpboxes-core
📄 许可证
MIT License
🔧 由 SharpBoxesCore 团队打造 —— 让 WPF 开发更简单!
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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.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.