您的位置:首页 > 运维架构

动态可订制属性的 PropertyGrid

2017-12-13 20:48 211 查看
文章转载,原文来自:http://blog.csdn.net/akron/article/details/2750566

在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 可以获得更多的功能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  propertygrid