前提条件
项目引入对应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();
}
问题思考
编辑器如何外部传入控件的多参数值,可以考虑自定义解析器。