PropertyGrid控件就是Visual Studio开发工具里面的属性浏览器,我们在VS里面可以通过属性浏览器查看,修改控件的属性,并主要通过使用反射来检索项目的属性。
一.如何显示属性
1)普通显示
在PropertyGrid中显示属性很容易,我们可以直接给propertyGrid1.SelectedObject属性赋值,SelectObject属性可以获取或设置当前选定的对象,数据类型为object,这就意味着我们可以直接将一个对象赋给它。针对一个对象,它会将对象中的所有公共属性显示在PropertyGrid上。假如我们定义一个Station类,如下
- public
class Station -
{ -
string _StationName; -
double _Lon = 103; -
double _Lat = 38; -
Color _color; -
string _file string.Empty;= -
Font _font; -
string FileName -
{ -
{ return_file; } -
{ _file = value; } -
} -
Color Color -
{ -
{ return_color; } -
{ _color = value; } -
} -
Font Font -
{ -
{ return_font; } -
{ _font = value; } -
} -
string StationName -
{ -
{ return_StationName; } -
{ _StationName = value; } -
} -
double Lon -
{ -
{ return_Lon; } -
{ _Lon = value; } -
} -
double Lat -
{ -
{ return_Lat; } -
{ _Lat = value; } -
} -
}
然后在窗体中拖拉一个PropertyGrid控件propertygrid1,在Form_load中代码如下
- private
void Form1_Load( objectsender, EventArgs e) - {
-
Station s= Station(); -
propertygrid1.SelectObject=s; - }
我们看到属性名显示都是英文,那样很不方便阅读如果我们像显示中文,该如何实现呢?
更改了显示方式
要更改某些属性的显示方式,您可以对这些属性应用不同的特性。特性是用于为类型、字段、方法和属性等编程元素添加批注的声明标记,在运行时可以使用反射对其进行检索。下面列出了其中的一部分:
DescriptionAttribute
BrowsableAttribute
ReadOnlyAttribute
DefaultValueAttribute
DefaultPropertyAttribute
下面我们在Station类中的属性Lon上方添加[CategoryAttribute("坐标"),DisplayNameAttribute("经度")],效果如下:
如果想要在属性表中添加颜色选择和字体选择那是很容易一件事,可以在Station类中添加Color类型属性,和Font类型属性,绑定后,就可以进行颜色选择和字体选择了,代码在Station中已经实现。
2)自定义显示
我们可以看出这种上面这种显示属性方法并不够灵活,我们不能方便的及时增加或者删除属性。
- "FONT-SIZE:
13px" >public class PropertyManageCls : CollectionBase, ICustomTypeDescriptor -
{ -
void Add(Property value) -
{ -
flag=-1; -
(value null)!= -
{ -
( base.List.Count>0) -
{ -
IList mList= List(); -
( inti base.List.Count;= 0; i < i++) -
{ -
Property p = as Property; -
(value.Name == p.Name) -
{ -
flag = i; -
} -
mList.Add(p); -
} -
(flag == -1) -
{ -
mList.Add(value); -
} -
-
(Property inp mList) -
{ -
-
} -
} -
-
{ -
-
} -
} -
} -
void Remove(Property value) -
{ -
-
-
} -
Property this[intindex] -
{ -
-
{ -
(Property) base.List[index]; -
} -
-
{ -
= (Property)value; -
} -
} -
#region ICustomTypeDescriptor 成员 -
AttributeCollection GetAttributes() -
{ -
TypeDescriptor.GetAttributes( this,true); -
} -
string GetClassName() -
{ -
TypeDescriptor.GetClassName( this,true); -
} -
string GetComponentName() -
{ -
TypeDescriptor.GetComponentName( this,true); -
} -
TypeConverter GetConverter() -
{ -
TypeDescriptor.GetConverter( this,true); -
} -
EventDescriptor GetDefaultEvent() -
{ -
TypeDescriptor.GetDefaultEvent( this,true); -
} -
PropertyDescriptor GetDefaultProperty() -
{ -
TypeDescriptor.GetDefaultProperty( this,true); -
} -
object GetEditor(Type editorBaseType) -
{ -
TypeDescriptor.GetEditor( this,editorBaseType, true); -
} -
EventDescriptorCollectio n GetEvents(Attribute[] attributes) -
{ -
TypeDescriptor.GetEvents( this,attributes, true); -
} -
EventDescriptorCollectio n GetEvents() -
{ -
TypeDescriptor.GetEvents( this,true); -
} -
PropertyDescriptorCollec tion GetProperties(Attribute[] attributes) -
{ -
PropertyDescriptor[] newProps = PropertyDescriptor[ this.Count]; -
( inti this.Count;= 0; i < i++) -
{ -
Property prop = (Property) -
newProps[i] = CustomPropertyDescriptor ref( prop, attributes); -
} -
new PropertyDescriptorCollec tion(newProps); -
} -
PropertyDescriptorCollec tion GetProperties() -
{ -
TypeDescriptor.GetProperties( this,true); -
} -
object GetPropertyOwner(PropertyDescriptor pd) -
{ -
this; -
} -
#endregion -
} - //属性类
-
class Property -
{ -
string _name= string.Empty; -
object _value= null; -
bool _readonly= false; -
bool _visible= true; -
string _category= string.Empty; -
TypeConverter _converter= -
_editor null;= -
string _displayname string.Empty;= -
Property( stringsName, objectsValue) -
{ -
= sName; -
= sValue; -
} -
Property( stringsName, objectsValue, boolsReadonly, boolsVisible) -
{ -
= sName; -
= sValue; -
= sReadonly; -
= sVisible; -
} -
string Name //获得属性名 -
{ -
-
{ -
_name; -
} -
-
{ -
_name=value; -
} -
} -
string DisplayName //属性显示名称 -
{ -
-
{ -
_displayname; -
} -
-
{ -
_displayname = value; -
} -
} -
TypeConverter //类型转换器,我们在制作下拉列表时需要用到Converter -
{ -
-
{ -
_converter; -
} -
-
{ -
_converter = value; -
} -
} -
string Category //属性所属类别 -
{ -
-
{ -
_category; -
} -
-
{ -
_category = value; -
} -
} -
object Value //属性值 -
{ -
-
{ -
_value; -
} -
-
{ -
_value=value; -
} -
} -
bool ReadOnly //是否为只读属性 -
{ -
-
{ -
_readonly; -
} -
-
{ -
_readonly = value; -
} -
} -
bool Visible //是否可见 -
{ -
-
{ -
_visible; -
} -
-
{ -
_visible = value; -
} -
} -
virtual object Editor //属性编辑器 -
{ -
-
{ -
_editor; -
} -
-
{ -
_editor = value; -
} -
} -
} -
class CustomPropertyDescriptor : PropertyDescriptor -
{ -
Property m_Property; -
CustomPropertyDescriptor ref( Property myProperty, Attribute[] attrs) -
: attrs) -
{ -
m_Property = myProperty; -
} -
#region PropertyDescriptor 重写方法 -
override bool CanResetValue( objectcomponent) -
{ -
false; -
} -
override Type ComponentType -
{ -
-
{ -
null; -
} -
} -
override object GetValue( objectcomponent) -
{ -
m_Property.Value; -
} -
override string Description -
{ -
-
{ -
m_Property.Name; -
} -
} -
override string Category -
{ -
-
{ -
m_Property.Category; -
} -
} -
override string DisplayName -
{ -
-
{ -
m_Property.DisplayName!= ""?m_Property.DisplayName:m_Property.Name; -
} -
} -
override bool IsReadOnly -
{ -
-
{ -
m_Property.ReadOnly; -
} -
} -
override void ResetValue( objectcomponent) -
{ -
to implement -
} -
override bool ShouldSerializeValue( objectcomponent) -
{ -
false; -
} -
override void SetValue( objectcomponent, objectvalue) -
{ -
m_Property.Value = value; -
} -
override TypeConverter Converter -
{ -
-
{ -
m_Property.Converter; -
} -
} -
override Type PropertyType -
{ -
{ returnm_Property.Value.GetType(); } -
} -
override object GetEditor(Type editorBaseType) -
{ -
m_Property.Editor== null?base.GetEditor(editorBaseType):m_Property.Editor; -
} -
#endregion -
}
下面我们来看看该如何使用,我们仍然在Form_load中添加代码如下:
- "FONT-SIZE:
13px" >PropertyManageCls pmc = PropertyManageCls(); -
Property pp = Property( "ID","1", false, true); -
pp.Category = -
pp.DisplayName = -
pmc.Add(pp); -
propertyGrid1.SelectObject=pmc;
我们可以看到上面的属性显示很简单,如果想要自定义一个下拉框,或者有一个路径选择的该怎么办呢。
1)类型转换器
要实现下拉框的方法:使用类型转换器,需要继承与TypeConverter或者StringConverter,然后重写方法,代码如下:
- "FONT-SIZE:
13px" > -
class DropDownListConverter : StringConverter -
{ -
m_Objects; -
DropDownListConverter( object[]objects) -
{ -
m_Objects = objects; -
} -
override bool GetStandardValuesSupport ed(ITypeDescriptorContext context) -
{ -
true; -
} -
override bool GetStandardValuesExclusi ve(ITypeDescriptorContext context) -
{ -
true;"LINE-HEIGHT: 15.39px; >//true下拉框不可编辑FONT-FAMILY: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; COLOR: rgb(0,130,0); FONT-SIZE: 14px" - "FONT-SIZE:
13px" > -
} -
override -
System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) -
{ -
new StandardValuesCollection //我们可以直接在内部定义一个数组,但并不建议这样做,这样对于下拉框的灵活(m_Objects); //性有很大影响 -
} -
}
我们实现了下拉框类型转换器,但该如何使用呢?
使用方法一:我们仍然以Station类作为例子,在属性上方添加标记[TypeConverter(typeof(DropDownListConverter))],但在这种情况下,我们需要预先在DropDownListConverter中定义下拉框内容。
使用方法二:这种方法我们可以在外部定义数组,使用方便,使用方法代码如下:
- "FONT-FAMILY:
Arial; >"FONT-SIZE:COLOR: #333333" 13px" >void Form_load( objectsender, EventArgs e) -
{ -
PropertyManageCls pmc = PropertyManageCls(); -
[]s= newstring[] { "1","2", "3", "4" }; -
Property pp = Property(txtname.Text,txtvalue.Text, false,true); -
pp.Category = -
pp.DisplayName = -
pp.Converter = DropDownListConverter(s); //Property的Converter属性就可以设置类型转换 -
pmc.Add(pp); -
propertyGrid1.SelectObject = pmc; -
}
2)属性编辑器
使用属性编辑器实现路径选择:属性编辑器需要继承与UITypeEditor
- "FONT-SIZE:
13px" >//文件路径选择public class PropertyGridFileItem : UITypeEditor -
{ -
-
override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context) -
{ -
-
UITypeEditorEditStyle.Modal; -
-
} -
-
override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System. -
- IServiceProvider
provider, objectvalue) -
{ -
-
IWindowsFormsEditorServi ce edSvc = -
(IWindowsFormsEditorServi ce)provider.GetService( ce)); -
-
(edSvc null)!= -
{ -
-
可以打开任何特定的对话框 -
-
OpenFileDialog dialog = OpenFileDialog(); -
-
dialog.AddExtension = -
-
(dialog.ShowDialog().Equals(DialogResult.OK)) -
{ -
-
dialog.FileName; -
-
} -
} -
-
value; -
-
} -
-
}
使用方法一:以Station类为例,在属性上方添加标记[EditorAttribute(typeof(PropertyGridFileItem),
使用方法二:使用方法代码如下:
- "FONT-SIZE:
13px" >void Form_load( objectsender, EventArgs e) -
{ -
PropertyManageCls pmc = PropertyManageCls(); -
Property pp = Property(txtname.Text,txtvalue.Text, false,true); -
pp.Category = -
pp.DisplayName = -
pp.Editor= PropertyGridFileItem(); //Property的Editor属性就可以设置属性编辑 -
pmc.Add(pp); -
propertyGrid1.SelectObject = pmc; -
}