运行时自定义PropertyGrid显示属性项目

运行时自定义PropertyGrid显示属性项目 简述

在PropertyGrid所显示的属性内容包括属性分类(Category)及组件属性,

在一般情况下直接使用PropertyGrid来显示一个对象的所有属性是非常方便的,只需一个语句就能完成:

propertyGrid.SelectedObject = component;

但在实际应用中可能会不需要显示所有属性项目,而是通过外部指定(通过XML等进行描述),这些设置一般情况下在创建组件时用代码中的Attribute来进行具体设置,如所属分类,显示标题等,这只能针对于一些自建的组件可以这么做。

问题描述

像上面所说,在创建自建组件时可以用Attribute的方式来设置PropertyGrid的显示样式,但这种方法不能应用于已有的组件,像系统中的TextBox,Button等,除非自己建立一个由这些组件派生的类,当然这样做会加大复杂度。像要实现下面所显示的这种效果在实际操作时会很麻烦。

左图是TextBox原有的所有属性,右图是经过处理后的属性

解决方法

在.Net中提供了一个自定义类型说明的接口(System.ComponentModel.ICustomTypeDescriptor),PropertyGrid可以直接自动处理用此接口生成的对象,因此在处理这个问题的时候只需要创建一个基于这个接口的处理类就可以达到世期望的目标,在这个接口中提供了GetProperties方法用于返回所选组件的所有属性,因此我们可以通过这个方法可以对我们所需要的属性进行过滤,下面是一段GetPropertys的处理代码:

 public PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
 { 
 List<CustomPropertyDescriptor> tmpPDCLst = new List<CustomPropertyDescriptor>(); 
 PropertyDescriptorCollection tmpPDC = TypeDescriptor.GetProperties(mCurrentSelectObject, attributes); 
 IEnumerator tmpIe = tmpPDC.GetEnumerator(); 
  CustomPropertyDescriptor tmpCPD; 
 PropertyDescriptor tmpPD; 
 while (tmpIe.MoveNext()) 
 { 
 tmpPD = tmpIe.Current as PropertyDescriptor; 
 if (mObjectAttribs.ContainsKey(tmpPD.Name)) 
 { 
 tmpCPD = new CustomPropertyDescriptor(mCurrentSelectObject, tmpPD); 
 tmpCPD.SetDisplayName(mObjectAttribs[tmpPD.Name]); 
          //此处用于处理属性分类的名称,可以在XML等设置文件中进行设置,在这段代码中只是简单的在分类后加了“中文”两个字 
 tmpCPD.SetCategory(tmpPD.Category + "中文"); 
 tmpPDCLst.Add(tmpCPD); 
  } 
 } 
 return new PropertyDescriptorCollection(tmpPDCLst.ToArray()); 
 } 

当然在进行属性过虑之后,PropertyGrid中所显示的属性名称都还是原有名称,若想同时改变在PropertyGrid中显示出来的名称则需要重写PropertyDescriptor中的部分方法,在上面这段代码中的CustomPropertyDescriptor就是一个基于PropertyDescriptor的类。 
在CustomPropertyDescriptor类中最主要的是重写DisplayName与Category这两个属性,但由于在PropertyDescriptor中这两个属性是只读的,因此在这个类中需要加入两个用于设置这两个属性的方法(或直接用Field)在这里我使用了SetDispalyName与SetCategory这两个方法: 

 private string mCategory; 
 public override string Category 
 { 
 get { return mCategory; } 
 } 
 private string mDisplayName ; 
 public override string DisplayName 
 { 
 get { return mDisplayName; } 
 } 
 public void SetDisplayName(string pDispalyName) 
 { 
 mDisplayName = pDispalyName; 
  } 
 public void SetCategory(string pCategory) 
 { 
 mCategory = pCategory; 
 } 
  就这样的几步,便可以将PropertyGrid中显示的内容完全自定义。 
在写ICustomTypeDescriptor接口时,其他的一些方法可以用TypeDescriptor直接返回相关方法调用,并在GetPropertyOwner方法中应返回当前选择对象否则将不会对修改值起任何作用 
 public object GetPropertyOwner(PropertyDescriptor pd) 
 { 
  return mCurrentSelectObject; 
 } 

在写CustomPropertyDescriptor类时需要一个PropertyDescriptor对象,在实现一些方法时直接返回这个对象的值。

当然也可以通过这个方法来自定义一些Events的输出, 使用方法 

//加载组件属性,从XML文件载入,此处为Button XmlNode tmpXNode = mXDoc.SelectSingleNode("Components/Component[@Name=\"Button\"]"); //选择属性设置 XmlNodeList tmpXPropLst = tmpXNode.SelectNodes("Propertys/Property"); //创建CustomProperty对象 CustomProperty cp = new CustomProperty(sender, tmpXPropLst); //设置PropertyGrid选择对象 propertyGrid1.SelectedObject = cp; 文件下载

源码

演示

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Alice

demo3同通讯录展示的方式分组排序

按A-Z顺序分组展示 有些项目中会需要这样的需求。形成类似于上述的界面。类似于通讯录里边的排序。实现的效果:所有的数据展示的时候,能够分组展示。顺序按照A-Z的...

2299
来自专栏跟着阿笨一起玩NET

C# Eval在aspx页面中的用法及作用

2762
来自专栏林德熙的博客

WPF 开发

如果使用NamedPipeServerStream、Mutex做单实例,需要传入字符串,这时如果传入一个固定的字符串,会在多用户的时候无法使用。

2451
来自专栏北京马哥教育

Python 中被忽略的 else

1444
来自专栏林欣哲

区块链开发之Go语言—IO操作

本篇文章是对区块链开发中的Go语言中常用的io操作的库做一个梳理 io,最基本的io Reader type Reader interface { Re...

3848
来自专栏守候书阁

编写自己的代码库(javascript常用实例的实现与封装--续)

这个系列的上一篇文章(编写自己的代码库(javascript常用实例的实现与封装))总结了34个常见的操作。但是在开发中,常见的实例又何止这么多个,经过这些日子...

1483
来自专栏蓝天

struct对齐问题

851
来自专栏前端那些事

自制刻度尺插件-前端简易实现"腾讯信用"界面

依据我现有的知识,在前端上"简易"的实现了腾讯信用的界面,同时自己自制了一个竖直的刻度尺插件,曲线的位置可以根据传入的数值动态的改变,这次主要也想总结一下关于j...

31111
来自专栏iOSer成长记录

OpenGL ES(二) 三角形

1523
来自专栏文武兼修ing——机器学习与IC设计

Python解决大规模二进制数据错位问题描述解决方法实验代码最终代码

问题描述 有一些二进制数据,每八位按顺序存为一个十进制数保存成CSV文件,每行为一个二进数数据,每个单元格均为一个十进制数。若数据为0000 0001 1000...

35110

扫码关注云+社区

领取腾讯云代金券