PropertyGrid 绑定动态的属性与值的集合
建立下面3个类:
- XProp
- XPropDescriptor
- XProps
建立Class XProp
XProp 就是用户将具体使用的属性。PropertyGrid 很炫的一点就是属性的定制可以有很大的自由度。在这里,给出一种最最简单的形式,属性包括 Name 和 Value 两个部分,在 PropertyGrid 的属性窗口中,Name 将代表左边的属性名称,Value 将代表右边的属性值。
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.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.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(this, true);
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}
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(this, true);
}
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(this, true);
}
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;
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;
我这个博客废弃不用了,今天想寻找外链的时候,突然想到这个博客权重很高。
有需要免费外链的,留言即可,我准备把这个博客变成免费的友情链接站点。