动态可订制属性的 PropertyGrid

VB6, VC++, C#.net 里都可以见到一个属性设计器,用来编辑修改 object 的属性。C# 下提供了一个属性设计器 PropertyGrid, 其使用极其简单,只要

 

      grid.SelectedObject = myOjbect;

 

就可以把myOjbect 的所有属性显示出来。不过很多时候我们不希望如此,因为欠缺一种灵活性。我希望可以自由的控制需要编辑的内容。能做的这一点,再配合可编辑的 ListView 可以很好的解决复杂内容的修改编辑问题。

 

首先是定义一个CProperty, 用来设置 object PropertyGrid 中的内容, 还得定义一个实现 ICustomTypeDescriptor 接口的容器CPropertyCollection, 最后定制一个 PropertyDescriptor, 用来描述 PropertyGrid 接口方法。

 

 

       public class CPropertyCollection : CCollection<CProperty>, ICustomTypeDescriptor

       {

              public void Add(CProperty value)

              {

                     base.Put(value.Name, value);

              }

 

              #region "TypeDescriptor"

 

              public String GetClassName()

              {

                     return TypeDescriptor.GetClassName(this, true);

              }

 

              public AttributeCollection GetAttributes()

              {

                     return TypeDescriptor.GetAttributes(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(Type editorBaseType)

              {

                     return TypeDescriptor.GetEditor(this, editorBaseType, true);

              }

 

              public EventDescriptorCollection GetEvents(Attribute[] attributes)

              {

                     return TypeDescriptor.GetEvents(this, attributes, true);

              }

 

              public EventDescriptorCollection GetEvents()

              {

                     return TypeDescriptor.GetEvents(this, true);

              }

 

              public PropertyDescriptorCollection GetProperties(Attribute[] attributes)

              {

                     PropertyDescriptor[] propDes = new PropertyDescriptor[this.Count];

                     for (int i = 0; i < this.Count; i++) {

                            CProperty prop = (CProperty) this[i];

                            propDes[i] = new CPropertyDescriptor(ref prop, attributes);

                     }

                     return new PropertyDescriptorCollection(propDes);

              }

 

              public PropertyDescriptorCollection GetProperties()

              {

                     return TypeDescriptor.GetProperties(this, true);

              }

 

              public object GetPropertyOwner(PropertyDescriptor pd)

              {

                     return this;

              }

              #endregion

       }

 

       public class CProperty

       {

              private string m_Name = string.Empty;

              private bool m_bReadOnly = false;

              private bool m_bVisible = true;

              private object m_Value = null;

              private string m_Category = string.Empty;

              TypeConverter m_Converter = null;

              object m_Editor = null;

 

 

              public CProperty(string name, object value)

              {

                     m_Name = name;

                     m_Value = value;

              }

 

              public CProperty(string name, object value, bool bReadOnly, bool bVisible)

              {

                     m_Name = name;

                     m_Value = value;

                     m_bReadOnly = bReadOnly;

                     m_bVisible = bVisible;

              }

 

              public bool ReadOnly

              {

                     get { return m_bReadOnly; }

                     set { m_bReadOnly = value; }

              }

 

              public virtual TypeConverter Converter

              {

                     get { return m_Converter; }

                     set { m_Converter = value; }

              }

 

              public string Name

              {

                     get { return m_Name; }

                     set { m_Name = value; }

              }

 

              public bool Visible

              {

                     get { return m_bVisible; }

                     set { m_bVisible = value; }

              }

 

              public virtual object Value

              {

                     get { return m_Value; }

                     set { m_Value = value; }

              }

 

              public string Category

              {

                     get { return m_Category; }

                     set { m_Category = value; }

              }

 

              public virtual object Editor

              {

                     get { return m_Editor; }

                     set { m_Editor = value;  }

              }

       }

 

 

       public class CPropertyDescriptor : PropertyDescriptor

       {

              CProperty m_Property;

 

              public CPropertyDescriptor(ref CProperty property, Attribute[] attrs)

                     : base(property.Name, attrs)

              {

                     m_Property = property;

              }

 

              #region PropertyDescriptor "region"

 

              public override bool CanResetValue(object component)

              {

                     return false;

              }

 

              public override Type ComponentType

              {

                     get { return null; }

              }

 

              public override object GetValue(object component)

              {

                     return m_Property.Value;

              }

 

              public override string Description

              {

                     get { return m_Property.Name; }

              }

 

              public override string Category

              {

                     get { return m_Property.Category; }

              }

 

              public override string DisplayName

              {

                     get { return m_Property.Name; }

              }

 

              public override bool IsReadOnly

              {

                     get { return m_Property.ReadOnly; }

              }

 

              public override TypeConverter Converter

              {

                     get { return m_Property.Converter; }

              }

 

              public override void ResetValue(object component)

              {

              }

 

              public override bool ShouldSerializeValue(object component)

              {

                     return false;

              }

 

              public override void SetValue(object component, object value)

              {

                     m_Property.Value = value;

              }

 

              public override Type PropertyType

              {

                     get { return m_Property.Value.GetType(); }

              }

 

              public override object GetEditor(Type editorBaseType)

              {

                     return m_Property.Editor == null ? base.GetEditor(editorBaseType) : m_Property.Editor;

              }

              #endregion

       }

 

 

 

下面的事情变得很简单:

 

       private void Form_Load(object sender, EventArgs e)

              {

                     CProperty myProp1 = new CProperty("Test1", "test");

                     MyProp1.Category = "test";

                     CProperty myProp2 = new CProperty("Test2", 1);

                     myProp2.Editor = new System.Drawing.Design.ColorEditor();

                     myProperties.Add(myProp1);

                     myProperties.Add(myProp2);

                     grid.SelectedObject = myProperties;

              }

 

 

可以看到通过CProperty.Editor 可以使用各种的编辑器,甚至自定义的编辑器(从 UITypeEditor 派生,msdn 中有例子)。另一个要点是CProperty.Converter, 用来自定义如何进行类型转换,例如,enum 类型在PropertyGrid 中用 List 编辑,如果不想事先定义一个 enum, 可以用自己的 TypeConverter 来实现功能更强大的编辑方法。

 

       public class ListConverter : StringConverter

       {

              object[] m_Objects;

              public ListConverter(object[] objects)

              {

                     m_Objects = objects;

              }

 

              public override bool GetStandardValuesSupported(ITypeDescriptorContext context)

              {

                     return true;

              }

              public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)

              {

                     return true;

              }

 

              public override

              System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)

              {

                     return new StandardValuesCollection(m_Objects);

              }

       } 

 

使用ListConverter

 

            CProperty myProp = new CProperty("Test", "test2");

            myProp.Converter = new ListConverter(new string[] { "test1", "test2", "test3" });

 

 

click 属性 Test 时,会弹出一个 List 框。重载 TypeConverter ConvertTo and ConvertFrom 可以获得更多的功能。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值