System.Windows.Forms.PropertyGrid的使用
.NET 框架 PropertyGrid 控件是 Visual Studio .NET 属性浏览器的核心。PropertyGrid 控件显示对象或类型的属性,并主要通过使用反射来检索项目的属性。当我们创建了一个类编译之后就生成了类的Metadata,元数据。PropertyGrid 就是使用反射来展示和修改类的公共属性的,就是public标识的属性。但凡成熟的软件都是使用配置来满足不同场景或者客户的需求,就是使用参数开关的形式。PropertyGrid 代表了主流的配置界面,对于实施培训的技术支持人员比较人性化。现在就来分享一下使用心得。
SelectedObject
PropertyGrid 的方法SelectedObject是获取或设置在网格中显示属性的对象。是使用PropertyGrid显示对象的最重要方法。
实际用例截图
使用的要点:
- 1)属性值如果是枚举类型,则设置改属性时自动生成下拉框和填充选择值。
- 2)属性可自定义分类
- 3)属性可注释和说明
- 4)属性设置可自定义属性类型
- 5)如果需要隐藏属性不在PropertyGrid里显示出来,可以在类的属性上标记[Browsable(false)]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | private string _动态内容; [Description( @"格式:{PropertyName[(Start[,Length])]}[&Blank[(Length)]]&{PropertyName[(Start[,Length])]} PropertyName:动态属性里的选项 Start:动态属性对应内容的开始位置 Length:截取内容的长度 Blank:空格 Length:空格的个数 &:为分隔符 设置此内容的时候,请务必小心,设置时系统不检测其值的合法性,在执行的时候可能会报错" ), Category("表达式")] [XmlAttribute( "动态内容" )] public string 动态内容 { get { return _动态内容; } set { _动态内容 = value; NotifyPropertyChanged( "动态内容" ); } } |
要更改某些属性的显示方式,您可以对这些属性应用不同的特性。特性是用于为类型、字段、方法和属性等编程元素添加批注的声明标记,在运行时可以使用反射对其进行检索。下面列出了其中的一部分:
DescriptionAttribute - 设置显示在属性下方说明帮助窗格中的属性文本。这是一种为活动属性(即具有焦点的属性)提供帮助文本的有效方法。
CategoryAttribute - 设置属性在网格中所属的类别。当您需要将属性按类别名称分组时,此特性非常有用。如果没有为属性指定类别,该属性将被分配给杂项 类别。可以将此特性应用于所有属性。
BrowsableAttribute – 表示是否在网格中显示属性。此特性可用于在网格中隐藏属性。默认情况下,公共属性始终显示在网格中。
ReadOnlyAttribute – 表示属性是否为只读。此特性可用于禁止在网格中编辑属性。默认情况下,带有 get 和 set 访问函数的公共属性在网格中是可以编辑的。
DefaultValueAttribute – 表示属性的默认值。如果希望为属性提供默认值,然后确定该属性值是否与默认值相同,则可使用此特性。可以将此特性应用于所有属性。
DefaultPropertyAttribute – 表示类的默认属性。在网格中选择某个类时,将首先突出显示该类的默认属性。
自定义PropertyGrid属性 请参考文章:http://blog.csdn.net/jjhua/article/details/23100143.
PropertyGrid显示英文字符为中文
PropertyGrid显示英文字符为中文,需要自定义属性和实现一个自定义的PropertyDescriptor子类,还有一个实现了"ICustomTypeDescriptor"接口的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | namespace GDIPrinterDriver { public delegate void PropertyChanged( object Value); /// <summary> /// 主要是实现中文化属性显示 /// </summary> public class PropertyBase : ICustomTypeDescriptor { AttributeCollection ICustomTypeDescriptor.GetAttributes() { return TypeDescriptor.GetAttributes( this , true ); } string ICustomTypeDescriptor.GetClassName() { return TypeDescriptor.GetClassName( this , true ); } string ICustomTypeDescriptor.GetComponentName() { return TypeDescriptor.GetComponentName( this , true ); } TypeConverter ICustomTypeDescriptor.GetConverter() { return TypeDescriptor.GetConverter( this , true ); } EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { return TypeDescriptor.GetDefaultEvent( this , true ); } PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { return null ; } object ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return TypeDescriptor.GetEditor( this , editorBaseType, true ); } EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { return TypeDescriptor.GetEvents( this , true ); } EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents( this , attributes, true ); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return ((ICustomTypeDescriptor) this ).GetProperties( new Attribute[0]); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { ArrayList props = new ArrayList(); Type thisType = this .GetType(); PropertyInfo[] pis = thisType.GetProperties(); foreach (PropertyInfo p in pis) { if (p.DeclaringType == thisType || p.PropertyType.ToString() == "System.Drawing.Color" ) { //判断属性是否显示 BrowsableAttribute Browsable = (BrowsableAttribute)Attribute.GetCustomAttribute(p, typeof (BrowsableAttribute)); if (Browsable != null ) { if (Browsable.Browsable == true || p.PropertyType.ToString() == "System.Drawing.Color" ) { PropertyStub psd = new PropertyStub(p, attributes); props.Add(psd); } } else { PropertyStub psd = new PropertyStub(p, attributes); props.Add(psd); } } } PropertyDescriptor[] propArray = (PropertyDescriptor[])props.ToArray( typeof (PropertyDescriptor)); return new PropertyDescriptorCollection(propArray); } object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { return this ; } } /// <summary> /// 自定义属性拦截器 /// </summary> public class PropertyStub : PropertyDescriptor { PropertyInfo info; public PropertyStub(PropertyInfo propertyInfo, Attribute[] attrs) : base (propertyInfo.Name, attrs) { info = propertyInfo; } public override Type ComponentType { get { return info.ReflectedType; } } public override bool IsReadOnly { get { return info.CanWrite == false ; } } public override Type PropertyType { get { return info.PropertyType; } } public override bool CanResetValue( object component) { return false ; } public override object GetValue( object component) { try { return info.GetValue(component, null ); } catch { return null ; } } public override void ResetValue( object component) { } public override void SetValue( object component, object value) { info.SetValue(component, value, null ); } public override bool ShouldSerializeValue( object component) { return false ; } //通过重载下面这个属性,可以将属性在PropertyGrid中的显示设置成中文 public override string DisplayName { get { if (info != null ) { ChnPropertyAttribute uicontrolattibute = (ChnPropertyAttribute)Attribute.GetCustomAttribute(info, typeof (ChnPropertyAttribute)); if (uicontrolattibute != null ) return uicontrolattibute.PropertyName; else { return info.Name; } } else return "" ; } } public override string Description { get { if (info != null ) { ChnPropertyAttribute uicontrolattibute = (ChnPropertyAttribute)Attribute.GetCustomAttribute(info, typeof (ChnPropertyAttribute)); if (uicontrolattibute != null ) return uicontrolattibute.PropertyDescription; } return string .Empty; } } } } |
然后在PropertyGrid需要维护的类上作自定义属性的标记。
1 2 3 4 5 6 7 8 9 10 11 12 | public class BarcodeElementNode : PropertyBase, IElementNodeData, INotifyPropertyChanged { private Point location; [ChnProperty( "位置" , "节点元素的在模板里的位置的坐标,鼠标选中节点即可以移动位置。" )] [Category( "通用属性" )] public Point Location { get { return location; } set { location = value; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /// <summary> /// 中文方式自定义属性标识 /// </summary> public class ChnPropertyAttribute : Attribute { private string _PropertyName; private string _PropertyDescription; public ChnPropertyAttribute( string Name, string Description) { _PropertyName = Name; _PropertyDescription = Description; } public ChnPropertyAttribute( string Name) { _PropertyName = Name; _PropertyDescription = "" ; } public string PropertyName { get { return _PropertyName; } } public string PropertyDescription { get { return _PropertyDescription; } } } |
好了。收工,不写点啥心慌。但是写好需要花很多时间。只是坚持一下吧
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool_2017_propertygrid.html
关于作者:20年编程从业经验,持续关注MES/ERP/POS/WMS/工业自动化
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
联系方式: qq:71008973;wx:6857740733
基于人脸识别的考勤系统 地址: https://gitee.com/afeng124/viewface_attendance_ext
自己开发安卓应用框架 地址: https://gitee.com/afeng124/android-app-frame
WPOS(warehouse+pos) 后台演示地址: http://47.239.106.75:8080/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!