HandyControl PropertyGrid及自定义编辑器
前提条件#
项目引入对应HandyControl对应版本包。
使用案例#
UI
部分#
<Window xmlns:hc="https://handyorg.github.io/handycontrol">
<hc:TabControl>
<hc:TabItem Header="默认样式">
<hc:PropertyGrid Width="380" SelectedObject="{Binding DemoModel}"/>
</hc:TabItem>
</hc:TabControl>
</Window>
数据实体#
实体类PropertyGridDemoModel.cs
public class PropertyGridDemoModel
{
[Category("类别1")]
[DisplayName("字符串")]
public string String { get; set; }
[Category("类别2")]
[DisplayName("整型")]
public int Integer { get; set; }
[Category("类别3")]
[DisplayName("布尔型")]
public bool Boolean { get; set; }
[Category("类别1")]
[DisplayName("枚举型")]
public Gender Enum { get; set; }
[DisplayName("枚举型")]
public HorizontalAlignment HorizontalAlignment { get; set; }
[DisplayName("枚举型")]
public VerticalAlignment VerticalAlignment { get; set; }
[DisplayName("图像类型")]
public ImageSource ImageSource { get; set; }
}
public enum Gender
{
[Description("男性")] //可考虑自定义编辑器,3.2不支持
Male,
[Description("女性")] //可考虑自定义编辑器,3.2不支持
Female
}
设置数据上下文#
当前为简化案例,直接在窗口后台进行上下文设置。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DemoModel = new PropertyGridDemoModel
{
String = "TestString",
Enum = Gender.Female,
Boolean = true,
Integer = 98,
VerticalAlignment = VerticalAlignment.Stretch
};
DataContext = this;
}
public PropertyGridDemoModel DemoModel { get; private set; }
}
运行效果一#
内置编辑器#
HandyControl
内置了一下基础类型的编辑器,具体如下:
名称 | 说明 |
---|---|
DatePropertyEditor | 日期编辑器 |
DateTimePropertyEditor | 日期时间编辑器 |
EnumPropertyEditor | 枚举编辑器 |
HorizontalAlignmentPropertyEditor | 水平对齐方式编辑器 |
ImagePropertyEditor | 图片编辑器 |
NumberPropertyEditor | 数字编辑器 |
PlainTextPropertyEditor | 纯文本编辑器 |
ReadOnlyTextPropertyEditor | 只读文本编辑器 |
SwitchPropertyEditor | 布尔编辑器(开关风格) |
TimePropertyEditor | 时间编辑器 |
VerticalAlignmentPropertyEditor | 垂直对齐方式编辑器 |
自定义编辑器#
内置编辑器毕竟是有限的,不少需求需要进行编辑器自定义,自定义编辑器需要实现基类 PropertyEditorBase
,假定需要实现一个带进度条的属性值,定义一个进度条编辑器,代码如下:
public class ProgressPropertyEditor : PropertyEditorBase
{
// 重写对应的控件构建类,用于返回UI需要显示的控件实例
public override FrameworkElement CreateElement(PropertyItem propertyItem)
{
var bar = new ProgressBar();
bar.Maximum = 100;
return bar;
}
// 设置对应实体属性与控件关联的依赖属性
public override DependencyProperty GetDependencyProperty()
{
return System.Windows.Controls.ProgressBar.ValueProperty;
}
}
添加属性并指定编辑器#
在PropertyGridDemoModel
中,添加一个属性ProgressValue
,并指定编辑器类型。
public class PropertyGridDemoModel
{
//省略重复内容
[Editor(typeof(ProgressPropertyEditor)
, typeof(ProgressPropertyEditor))] // 必须指定编辑器!!!
[DisplayName("自定义")]
public int ProgressValue { get; set; }
//省略重复内容
}
//省略重复内容
MainWindow.cs
设置属性值。
public partial class MainWindow : Window
{
public MainWindow()
{
//省略重复
DemoModel = new PropertyGridDemoModel
{
//省略重复
ProgressValue = 12,// 模拟设置属性值
//省略重复
};
//省略重复
}
//省略重复
}
运行效果二#
代码解析#
控件PropertyGrid
逻辑代码#
// 应用模板
public override void OnApplyTemplate()
{
// 省略代码
UpdateItems(SelectedObject);
}
private void UpdateItems(object obj)
{
if (obj != null && _itemsControl != null)
{
_dataView = CollectionViewSource.GetDefaultView((from item in TypeDescriptor.GetProperties(obj.GetType()).OfType<PropertyDescriptor>(
where PropertyResolver.ResolveIsBrowsable(item)
select item).Select(CreatePropertyItem).Do(delegate (PropertyItem item)
{
item.InitElement();
}));
SortByCategory(null, null);
_itemsControl.ItemsSource = _dataView;
}
}
protected virtual PropertyItem CreatePropertyItem(PropertyDescriptor propertyDescriptor)
{
return new PropertyItem
{
// 省略代码
// 获取编辑器
Editor = PropertyResolver.ResolveEditor(propertyDescriptor),
};
}
属性解析器PropertyResolver
#
public PropertyEditorBase ResolveEditor(PropertyDescriptor propertyDescriptor)
{
EditorAttribute editorAttribute = propertyDescriptor.Attributes.OfType<EditorAttribute>().FirstOrDefault();
if (editorAttribute != null && !string.IsNullOrEmpty(editorAttribute.EditorTypeName))
{
// 获取自定义编辑器
return CreateEditor(Type.GetType(editorAttribute.EditorTypeName));
}
// 创建内置编辑器实例
return CreateDefaultEditor(propertyDescriptor.PropertyType);
}
// 创建自定义编辑器实例
public virtual PropertyEditorBase CreateEditor(Type type)
{
return (Activator.CreateInstance(type) as PropertyEditorBase) ?? new ReadOnlyTextPropertyEditor();
}
问题思考#
编辑器如何外部传入控件的多参数值,可以考虑自定义解析器。
作者:关关长语
出处:https://www.cnblogs.com/guanguanchangyu/p/18076262
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
WPF
, HandyControl
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)