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

建立下面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

 

posted @ 2012-02-09 08:56  大气象  阅读(7955)  评论(2编辑  收藏  举报
http://www.tianqiweiqi.com