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

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

简述

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

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

propertyGrid.SelectedObject = component;<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

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

问题描述

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

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

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

o_propertygrid_1.JPGo_propertygrid_2.JPG 

解决方法

.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类中最主要的是重写DisplayNameCategory这两个属性,但由于在PropertyDescriptor中这两个属性是只读的,因此在这个类中需要加入两个用于设置这两个属性的方法(或直接用Field)在这里我使用了SetDispalyNameSetCategory这两个方法:

      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;

文件下载
 

源码
演示

转载于:https://www.cnblogs.com/pvistely/archive/2006/02/09/327656.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值