PropertyGrid 绑定动态的属性与值的集合

本文介绍如何通过自定义XProp、XPropDescriptor及XProps类来实现PropertyGrid的属性定制,以便于用户能够自由地设置属性的Name和Value,并通过实例演示了如何在界面上展示这些属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

建立下面3个类:

  • XProp
  • XPropDescriptor
  • XProps

建立Class XProp

XProp 就是用户将具体使用的属性。PropertyGrid 很炫的一点就是属性的定制可以有很大的自由度。在这里,给出一种最最简单的形式,属性包括 Name 和 Value 两个部分,在 PropertyGrid 的属性窗口中,Name 将代表左边的属性名称,Value 将代表右边的属性值。

using System;   
using System.ComponentModel;   
using System.Collections.Generic;   
using System.Text;   
  
namespace CustomerPropertyGrid   
{   
     class XProp   
    {   
         private  string theName =  "";   
         private  object theValue =  null;   
  
         public  string Name   
        {   
             get  
            {   
                 return  this.theName;   
            }   
             set  
            {   
                 this.theName = value;   
            }   
        }   
         public  object Value   
        {   
             get  
            {   
                 return  this.theValue;   
            }   
             set  
            {   
                 this.theValue = value;   
            }   
        }   
  
         public  override  string ToString()   
        {   
             return  " Name:  " + Name +  " , Value:  " + Value;   
        }   
    }   
}  

这个Class没有特别的地方,对 ToString 的 Overrides 是为了方便后面对整个类的内容显示。

建立Class XPropDescriptor

XPropDescriptior 是建立在 XProp 基础上的,同时是 PropertyDescriptor 的一个派生类。PropertyDescriptor是在 System.ComponentModel 中的,包含了 PropertyGrid 中每个属性所对应的各种接口。XPropDescriptior 就是把 XProp 中的属性和这些接口对应起来。

using System;   
using System.ComponentModel;   
using System.Collections.Generic;   
using System.Text;   
  
namespace CustomerPropertyGrid   
{   
     class XPropDescriptor : PropertyDescriptor   
    {   
        XProp theProp;   
  
         public XPropDescriptor(XProp prop, Attribute[] attrs) :  base(prop.Name,attrs)   
        {   
            theProp = prop;   
        }   
  
         public  override  bool CanResetValue( object component)   
        {   
             return  false;   
        }   
  
         public  override System.Type ComponentType   
        {   
             get {  return  this.GetType(); }   
        }   
  
         public  override  object GetValue( object component)   
        {   
             return theProp.Value;   
        }   
  
         public  override  bool IsReadOnly   
        {   
             get {  return  false; }   
        }   
  
         public  override System.Type PropertyType   
        {   
             get {  return theProp.Value.GetType(); }   
        }   
  
         public  override  void ResetValue( object component)   
        {   
        }   
  
         public  override  void SetValue( object component,  object value)   
        {   
            theProp.Value = value;   
        }   
  
         public  override  bool ShouldSerializeValue( object component)   
        {   
             return  false;   
        }   
    }   
}  

 

这一段程序中,大部分都是返回缺省值。需要注意的是下面的部分。

  • New
    这个部分把 XProp 的对象导入到类中,存储在变量 theProp 里面,成为将用户属性和 PropertyGrid 使用的属性对应的基础。
  • GetValue
    把存储在 XProp 中的属性值放到 PropertyGrid 里面。
  • SetValue
    把用户通过画面在 PropertyGrid 中修改了的属性值存储到 XProp 里面。
  • PropertyType
    指定这个属性的类型。PropertyGrid 是可以利用不同的类型来选择对应的属性值对话框的。

建立Class XProps

XProps 其实就是 XProp 的 Collection。这很容易,只要用一行代码,继承 System.Collections.Generic.List(Of XProp) 就搞定了。(希望你是了解 Generic 类的,这玩意是 .Net Framework 2.0里面的。)

另一方面,XProps 又需要实现 ICustomTypeDescriptor 的接口,这样把这个类的对象和 PropertyGrid 关联起来的时候,PropertyGrid 就会使用用户自定义的部分来构成属性窗口,而不是用这个类本身的程序Property来构成属性窗口。

using System.ComponentModel;   
using System.Collections.Generic;   
using System.Text;   
  
namespace CustomerPropertyGrid   
{   
     class XProps : List<XProp>, ICustomTypeDescriptor   
    {  
         #region ICustomTypeDescriptor 成员   
  
         public AttributeCollection GetAttributes()   
        {   
             return TypeDescriptor.GetAttributes( this, true);   
        }   
  
         public  string GetClassName()   
        {   
             return TypeDescriptor.GetClassName( thistrue);   
        }   
  
         public  string GetComponentName()   
        {   
             return TypeDescriptor.GetComponentName( thistrue);   
        }   
  
         public TypeConverter GetConverter()   
        {   
             return TypeDescriptor.GetConverter( thistrue);   
        }   
  
         public EventDescriptor GetDefaultEvent()   
        {   
             return TypeDescriptor.GetDefaultEvent( thistrue);   
        }   
  
         public PropertyDescriptor GetDefaultProperty()   
        {   
             return TypeDescriptor.GetDefaultProperty( thistrue);   
        }   
  
         public  object GetEditor(System.Type editorBaseType)   
        {   
             return TypeDescriptor.GetEditor( this, editorBaseType,  true);   
        }   
  
         public EventDescriptorCollection GetEvents(System.Attribute[] attributes)   
        {   
             return TypeDescriptor.GetEvents( this, attributes,  true);   
        }   
  
         public EventDescriptorCollection GetEvents()   
        {   
             return TypeDescriptor.GetEvents( thistrue);   
        }   
  
         public PropertyDescriptorCollection GetProperties(System.Attribute[] attributes)   
        {   
            PropertyDescriptor[] props =  new PropertyDescriptor[ this.Count];   
             for ( int i =  0; i <  this.Count; i++)   
            {   
                props[i] =  new XPropDescriptor( this[i], attributes);   
            }   
             return  new PropertyDescriptorCollection(props);   
        }   
  
         public PropertyDescriptorCollection GetProperties()   
        {   
             return TypeDescriptor.GetProperties( thistrue);   
        }   
  
         public  object GetPropertyOwner(PropertyDescriptor pd)   
        {   
             return  this;   
        }  
 
         #endregion   
  
         public  override  string ToString()   
        {   
            StringBuilder sb =  new StringBuilder();   
             for ( int i =  0; i <  this.Count; i++)   
            {   
                sb.Append( " [ " + i +  " " +  this[i].ToString() + System.Environment.NewLine);   
            }   
             return sb.ToString();   
        }   
    }   
}  

 

这段代码虽然比较冗长,不过读起来并不费力的。

ICustomTypeDescriptor 的实现部分中绝大部分是用 TypeDescriptor中 的成员实现的。只有 GetProperties 是另外写的,这个部分也很简单,就是把 Collection 里面的内容构成一个 PropertyDescriptor 集合,在用这个数组构成 PropertyDescriptorCollection 返回。

需要指出的是,也可以用 Dictionary 或者其他类型的 Collection 来构成这个类,差别部分也就是GetProperties 的写法不同而已。

剩下的部分就是对 ToString 的 Overrides 了,是为了方便后面对整个类的内容显示。这段程序里面使用了 StringBuilder,是属于 System.Text 的。在进行很多字符串组合的时候,这比用运算符 (&) 速度快很多。

界面代码

XProp[] xprop =  new XProp[ 3];   
  
            xprop[ 0] =  new XProp();   
            xprop[ 0].Name =  " A ";   
            xprop[ 0].Value =  " 1 ";   
            xprop[ 1] =  new XProp();   
            xprop[ 1].Name =  " B ";   
            xprop[ 1].Value =  " 2 ";   
            xprop[ 2] =  new XProp();   
            xprop[ 2].Name =  " C ";   
            xprop[ 2].Value =  " 3 ";   

            XProps xps= new XProps();
            xps.Add(xprop[ 0]);
            xps.Add(xprop[ 1]);
            xps.Add(xprop[ 2]);

            propertyGrid1.SelectedObject = xps;
url: http://greatverve.cnblogs.com/archive/2012/02/08/propertygird-bind.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值