网络转载,原文来自:http://blog.csdn.net/lxping1012/article/details/7073944

最近用到了PropertyGrid,原来从来没用到过,拿在手里,一头雾水,经过一段时间研究后,大概理解了Property的使用方法,下面仔细剖析一下。

PropertyGrid控件就是Visual Studio开发工具里面的属性浏览器,我们在VS里面可以通过属性浏览器查看,修改控件的属性,并主要通过使用反射来检索项目的属性。

一.如何显示属性

1)普通显示

在PropertyGrid中显示属性很容易,我们可以直接给propertyGrid1.SelectedObject属性赋值,SelectObject属性可以获取或设置当前选定的对象,数据类型为object,这就意味着我们可以直接将一个对象赋给它。针对一个对象,它会将对象中的所有公共属性显示在PropertyGrid上。假如我们定义一个Station类,如下

[csharp] view plaincopy
  1. public class Station
  2. {
  3. private string _StationName;
  4. private double _Lon = 103;
  5. private double _Lat = 38;
  6. private Color _color;
  7. private string _file = string.Empty;
  8. private Font _font;
  9. public string FileName
  10. {
  11. get { return _file; }
  12. set { _file = value; }
  13. }
  14. public Color Color
  15. {
  16. get { return _color; }
  17. set { _color = value; }
  18. }
  19. public Font Font
  20. {
  21. get { return _font; }
  22. set { _font = value; }
  23. }
  24. public string StationName
  25. {
  26. get { return _StationName; }
  27. set { _StationName = value; }
  28. }
  29. public double Lon
  30. {
  31. get { return _Lon; }
  32. set { _Lon = value; }
  33. }
  34. public double Lat
  35. {
  36. get { return _Lat; }
  37. set { _Lat = value; }
  38. }
  39. }
[csharp] view plain copy
  1. public class Station
  2. {
  3. private string _StationName;
  4. private double _Lon = 103;
  5. private double _Lat = 38;
  6. private Color _color;
  7. private string _file = string.Empty;
  8. private Font _font;
  9. public string FileName
  10. {
  11. get { return _file; }
  12. set { _file = value; }
  13. }
  14. public Color Color
  15. {
  16. get { return _color; }
  17. set { _color = value; }
  18. }
  19. public Font Font
  20. {
  21. get { return _font; }
  22. set { _font = value; }
  23. }
  24. public string StationName
  25. {
  26. get { return _StationName; }
  27. set { _StationName = value; }
  28. }
  29. public double Lon
  30. {
  31. get { return _Lon; }
  32. set { _Lon = value; }
  33. }
  34. public double Lat
  35. {
  36. get { return _Lat; }
  37. set { _Lat = value; }
  38. }
  39. }

然后在窗体中拖拉一个PropertyGrid控件propertygrid1,在Form_load中代码如下

[csharp] view plaincopy
  1. private void Form1_Load(object sender, EventArgs e)
  2. {
  3. Station s=new Station();
  4. propertygrid1.SelectObject=s;
  5. }
[csharp] view plain copy
  1. private void Form1_Load(object sender, EventArgs e)
  2. {
  3. Station s=new Station();
  4. propertygrid1.SelectObject=s;
  5. }

我们就可以看到如下效果:

我们看到属性名显示都是英文,那样很不方便阅读如果我们像显示中文,该如何实现呢?

更改了显示方式

要更改某些属性的显示方式,您可以对这些属性应用不同的特性。特性是用于为类型、字段、方法和属性等编程元素添加批注的声明标记,在运行时可以使用反射对其进行检索。下面列出了其中的一部分:

DescriptionAttribute - 设置显示在属性下方说明帮助窗格中的属性文本。这是一种为活动属性(即具有焦点的属性)提供帮助文本的有效方法。

CategoryAttribute - 设置属性在网格中所属的类别。当您需要将属性按类别名称分组时,此特性非常有用。如果没有为属性指定类别,该属性将被分配给杂项 类别。可以将此特性应用于所有属性。

BrowsableAttribute –  表示是否在网格中显示属性。此特性可用于在网格中隐藏属性。默认情况下,公共属性始终显示在网格中。

ReadOnlyAttribute –  表示属性是否为只读。此特性可用于禁止在网格中编辑属性。默认情况下,带有 get 和 set 访问函数的公共属性在网格中是可以编辑的。

DefaultValueAttribute –  表示属性的默认值。如果希望为属性提供默认值,然后确定该属性值是否与默认值相同,则可使用此特性。可以将此特性应用于所有属性。

DefaultPropertyAttribute –  表示类的默认属性。在网格中选择某个类时,将首先突出显示该类的默认属性。

下面我们在Station类中的属性Lon上方添加[CategoryAttribute("坐标"),DisplayNameAttribute("经度")],效果如下:

如果想要在属性表中添加颜色选择和字体选择那是很容易一件事,可以在Station类中添加Color类型属性,和Font类型属性,绑定后,就可以进行颜色选择和字体选择了,代码在Station中已经实现。

2)自定义显示

我们可以看出这种上面这种显示属性方法并不够灵活,我们不能方便的及时增加或者删除属性。

//属性表管理类

[csharp] view plaincopy
  1. <span style="font-size: 13px;"> public class PropertyManageCls : CollectionBase, ICustomTypeDescriptor
  2. {
  3. public void Add(Property value)
  4. {
  5. int flag=-1;
  6. if (value != null)
  7. {
  8. if (base.List.Count>0)
  9. {
  10. IList <Property> mList=new List<Property>();
  11. for (int i = 0; i < base.List.Count; i++)
  12. {
  13. Property p = base.List[i] as Property;
  14. if (value.Name == p.Name)
  15. {
  16. flag = i;
  17. }
  18. mList.Add(p);
  19. }
  20. if (flag == -1)
  21. {
  22. mList.Add(value);
  23. }
  24. base.List.Clear();
  25. foreach (Property p in mList)
  26. {
  27. base.List.Add(p);
  28. }
  29. }
  30. else
  31. {
  32. base.List.Add(value);
  33. }
  34. }
  35. }
  36. public void Remove(Property value)
  37. {
  38. if(value!=null&&base.List.Count>0)
  39. base.List.Remove(value);
  40. }
  41. public Property this[int index]
  42. {
  43. get
  44. {
  45. return (Property)base.List[index];
  46. }
  47. set
  48. {
  49. base.List[index] = (Property)value;
  50. }
  51. }
  52. #region ICustomTypeDescriptor 成员
  53. public AttributeCollection GetAttributes()
  54. {
  55. return TypeDescriptor.GetAttributes(this,true);
  56. }
  57. public string GetClassName()
  58. {
  59. return TypeDescriptor.GetClassName(this, true);
  60. }
  61. public string GetComponentName()
  62. {
  63. return TypeDescriptor.GetComponentName(this, true);
  64. }
  65. public TypeConverter GetConverter()
  66. {
  67. return TypeDescriptor.GetConverter(this, true);
  68. }
  69. public EventDescriptor GetDefaultEvent()
  70. {
  71. return TypeDescriptor.GetDefaultEvent(this, true);
  72. }
  73. public PropertyDescriptor GetDefaultProperty()
  74. {
  75. return TypeDescriptor.GetDefaultProperty(this, true);
  76. }
  77. public object GetEditor(Type editorBaseType)
  78. {
  79. return TypeDescriptor.GetEditor(this, editorBaseType, true);
  80. }
  81. public EventDescriptorCollection GetEvents(Attribute[] attributes)
  82. {
  83. return TypeDescriptor.GetEvents(this, attributes, true);
  84. }
  85. public EventDescriptorCollection GetEvents()
  86. {
  87. return TypeDescriptor.GetEvents(this,true);
  88. }
  89. public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
  90. {
  91. PropertyDescriptor[] newProps = new PropertyDescriptor[this.Count];
  92. for (int i = 0; i < this.Count; i++)
  93. {
  94. Property prop = (Property)this[i];
  95. newProps[i] = new CustomPropertyDescriptor(ref prop, attributes);
  96. }
  97. return new PropertyDescriptorCollection(newProps);
  98. }
  99. public PropertyDescriptorCollection GetProperties()
  100. {
  101. return TypeDescriptor.GetProperties(this, true);
  102. }
  103. public object GetPropertyOwner(PropertyDescriptor pd)
  104. {
  105. return this;
  106. }
  107. #endregion
  108. }
  109. //属性类
  110. public class Property
  111. {
  112. private string _name=string.Empty;
  113. private object _value=null;
  114. private bool _readonly=false;
  115. private bool _visible=true;
  116. private string _category=string.Empty;
  117. TypeConverter _converter=null;
  118. object _editor = null;
  119. private string _displayname = string.Empty;
  120. public Property(string sName, object sValue)
  121. {
  122. this._name = sName;
  123. this._value = sValue;
  124. }
  125. public Property(string sName, object sValue, bool sReadonly, bool sVisible)
  126. {
  127. this._name = sName;
  128. this._value = sValue;
  129. this._readonly = sReadonly;
  130. this._visible = sVisible;
  131. }
  132. public string Name  //获得属性名
  133. {
  134. get
  135. {
  136. return _name;
  137. }
  138. set
  139. {
  140. _name=value;
  141. }
  142. }
  143. public string DisplayName   //属性显示名称
  144. {
  145. get
  146. {
  147. return _displayname;
  148. }
  149. set
  150. {
  151. _displayname = value;
  152. }
  153. }
  154. public TypeConverter Converter  //类型转换器,我们在制作下拉列表时需要用到
  155. {
  156. get
  157. {
  158. return _converter;
  159. }
  160. set
  161. {
  162. _converter = value;
  163. }
  164. }
  165. public string Category  //属性所属类别
  166. {
  167. get
  168. {
  169. return _category;
  170. }
  171. set
  172. {
  173. _category = value;
  174. }
  175. }
  176. public object Value  //属性值
  177. {
  178. get
  179. {
  180. return _value;
  181. }
  182. set
  183. {
  184. _value=value;
  185. }
  186. }
  187. public bool ReadOnly  //是否为只读属性
  188. {
  189. get
  190. {
  191. return _readonly;
  192. }
  193. set
  194. {
  195. _readonly = value;
  196. }
  197. }
  198. public bool Visible  //是否可见
  199. {
  200. get
  201. {
  202. return _visible;
  203. }
  204. set
  205. {
  206. _visible = value;
  207. }
  208. }
  209. public virtual object Editor   //属性编辑器
  210. {
  211. get
  212. {
  213. return _editor;
  214. }
  215. set
  216. {
  217. _editor = value;
  218. }
  219. }
  220. }
  221. public class CustomPropertyDescriptor : PropertyDescriptor
  222. {
  223. Property m_Property;
  224. public CustomPropertyDescriptor(ref Property myProperty, Attribute[] attrs)
  225. : base(myProperty.Name, attrs)
  226. {
  227. m_Property = myProperty;
  228. }
  229. #region PropertyDescriptor 重写方法
  230. public override bool CanResetValue(object component)
  231. {
  232. return false;
  233. }
  234. public override Type ComponentType
  235. {
  236. get
  237. {
  238. return null;
  239. }
  240. }
  241. public override object GetValue(object component)
  242. {
  243. return m_Property.Value;
  244. }
  245. public override string Description
  246. {
  247. get
  248. {
  249. return m_Property.Name;
  250. }
  251. }
  252. public override string Category
  253. {
  254. get
  255. {
  256. return m_Property.Category;
  257. }
  258. }
  259. public override string DisplayName
  260. {
  261. get
  262. {
  263. return m_Property.DisplayName!=""?m_Property.DisplayName:m_Property.Name;
  264. }
  265. }
  266. public override bool IsReadOnly
  267. {
  268. get
  269. {
  270. return m_Property.ReadOnly;
  271. }
  272. }
  273. public override void ResetValue(object component)
  274. {
  275. //Have to implement
  276. }
  277. public override bool ShouldSerializeValue(object component)
  278. {
  279. return false;
  280. }
  281. public override void SetValue(object component, object value)
  282. {
  283. m_Property.Value = value;
  284. }
  285. public override TypeConverter Converter
  286. {
  287. get
  288. {
  289. return m_Property.Converter;
  290. }
  291. }
  292. public override Type PropertyType
  293. {
  294. get { return m_Property.Value.GetType(); }
  295. }
  296. public override object GetEditor(Type editorBaseType)
  297. {
  298. return m_Property.Editor==null? base.GetEditor(editorBaseType):m_Property.Editor;
  299. }
  300. #endregion
  301. }</span>
[csharp] view plain copy
  1. <span style="font-size: 13px;" data-filtered="filtered"> public class PropertyManageCls : CollectionBase, ICustomTypeDescriptor
  2. {
  3. public void Add(Property value)
  4. {
  5. int flag=-1;
  6. if (value != null)
  7. {
  8. if (base.List.Count>0)
  9. {
  10. IList <Property> mList=new List<Property>();
  11. for (int i = 0; i < base.List.Count; i++)
  12. {
  13. Property p = base.List[i] as Property;
  14. if (value.Name == p.Name)
  15. {
  16. flag = i;
  17. }
  18. mList.Add(p);
  19. }
  20. if (flag == -1)
  21. {
  22. mList.Add(value);
  23. }
  24. base.List.Clear();
  25. foreach (Property p in mList)
  26. {
  27. base.List.Add(p);
  28. }
  29. }
  30. else
  31. {
  32. base.List.Add(value);
  33. }
  34. }
  35. }
  36. public void Remove(Property value)
  37. {
  38. if(value!=null&&base.List.Count>0)
  39. base.List.Remove(value);
  40. }
  41. public Property this[int index]
  42. {
  43. get
  44. {
  45. return (Property)base.List[index];
  46. }
  47. set
  48. {
  49. base.List[index] = (Property)value;
  50. }
  51. }
  52. #region ICustomTypeDescriptor 成员
  53. public AttributeCollection GetAttributes()
  54. {
  55. return TypeDescriptor.GetAttributes(this,true);
  56. }
  57. public string GetClassName()
  58. {
  59. return TypeDescriptor.GetClassName(this, true);
  60. }
  61. public string GetComponentName()
  62. {
  63. return TypeDescriptor.GetComponentName(this, true);
  64. }
  65. public TypeConverter GetConverter()
  66. {
  67. return TypeDescriptor.GetConverter(this, true);
  68. }
  69. public EventDescriptor GetDefaultEvent()
  70. {
  71. return TypeDescriptor.GetDefaultEvent(this, true);
  72. }
  73. public PropertyDescriptor GetDefaultProperty()
  74. {
  75. return TypeDescriptor.GetDefaultProperty(this, true);
  76. }
  77. public object GetEditor(Type editorBaseType)
  78. {
  79. return TypeDescriptor.GetEditor(this, editorBaseType, true);
  80. }
  81. public EventDescriptorCollection GetEvents(Attribute[] attributes)
  82. {
  83. return TypeDescriptor.GetEvents(this, attributes, true);
  84. }
  85. public EventDescriptorCollection GetEvents()
  86. {
  87. return TypeDescriptor.GetEvents(this,true);
  88. }
  89. public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
  90. {
  91. PropertyDescriptor[] newProps = new PropertyDescriptor[this.Count];
  92. for (int i = 0; i < this.Count; i++)
  93. {
  94. Property prop = (Property)this[i];
  95. newProps[i] = new CustomPropertyDescriptor(ref prop, attributes);
  96. }
  97. return new PropertyDescriptorCollection(newProps);
  98. }
  99. public PropertyDescriptorCollection GetProperties()
  100. {
  101. return TypeDescriptor.GetProperties(this, true);
  102. }
  103. public object GetPropertyOwner(PropertyDescriptor pd)
  104. {
  105. return this;
  106. }
  107. #endregion
  108. }
  109. //属性类
  110. public class Property
  111. {
  112. private string _name=string.Empty;
  113. private object _value=null;
  114. private bool _readonly=false;
  115. private bool _visible=true;
  116. private string _category=string.Empty;
  117. TypeConverter _converter=null;
  118. object _editor = null;
  119. private string _displayname = string.Empty;
  120. public Property(string sName, object sValue)
  121. {
  122. this._name = sName;
  123. this._value = sValue;
  124. }
  125. public Property(string sName, object sValue, bool sReadonly, bool sVisible)
  126. {
  127. this._name = sName;
  128. this._value = sValue;
  129. this._readonly = sReadonly;
  130. this._visible = sVisible;
  131. }
  132. public string Name  //获得属性名
  133. {
  134. get
  135. {
  136. return _name;
  137. }
  138. set
  139. {
  140. _name=value;
  141. }
  142. }
  143. public string DisplayName   //属性显示名称
  144. {
  145. get
  146. {
  147. return _displayname;
  148. }
  149. set
  150. {
  151. _displayname = value;
  152. }
  153. }
  154. public TypeConverter Converter  //类型转换器,我们在制作下拉列表时需要用到
  155. {
  156. get
  157. {
  158. return _converter;
  159. }
  160. set
  161. {
  162. _converter = value;
  163. }
  164. }
  165. public string Category  //属性所属类别
  166. {
  167. get
  168. {
  169. return _category;
  170. }
  171. set
  172. {
  173. _category = value;
  174. }
  175. }
  176. public object Value  //属性值
  177. {
  178. get
  179. {
  180. return _value;
  181. }
  182. set
  183. {
  184. _value=value;
  185. }
  186. }
  187. public bool ReadOnly  //是否为只读属性
  188. {
  189. get
  190. {
  191. return _readonly;
  192. }
  193. set
  194. {
  195. _readonly = value;
  196. }
  197. }
  198. public bool Visible  //是否可见
  199. {
  200. get
  201. {
  202. return _visible;
  203. }
  204. set
  205. {
  206. _visible = value;
  207. }
  208. }
  209. public virtual object Editor   //属性编辑器
  210. {
  211. get
  212. {
  213. return _editor;
  214. }
  215. set
  216. {
  217. _editor = value;
  218. }
  219. }
  220. }
  221. public class CustomPropertyDescriptor : PropertyDescriptor
  222. {
  223. Property m_Property;
  224. public CustomPropertyDescriptor(ref Property myProperty, Attribute[] attrs)
  225. : base(myProperty.Name, attrs)
  226. {
  227. m_Property = myProperty;
  228. }
  229. #region PropertyDescriptor 重写方法
  230. public override bool CanResetValue(object component)
  231. {
  232. return false;
  233. }
  234. public override Type ComponentType
  235. {
  236. get
  237. {
  238. return null;
  239. }
  240. }
  241. public override object GetValue(object component)
  242. {
  243. return m_Property.Value;
  244. }
  245. public override string Description
  246. {
  247. get
  248. {
  249. return m_Property.Name;
  250. }
  251. }
  252. public override string Category
  253. {
  254. get
  255. {
  256. return m_Property.Category;
  257. }
  258. }
  259. public override string DisplayName
  260. {
  261. get
  262. {
  263. return m_Property.DisplayName!=""?m_Property.DisplayName:m_Property.Name;
  264. }
  265. }
  266. public override bool IsReadOnly
  267. {
  268. get
  269. {
  270. return m_Property.ReadOnly;
  271. }
  272. }
  273. public override void ResetValue(object component)
  274. {
  275. //Have to implement
  276. }
  277. public override bool ShouldSerializeValue(object component)
  278. {
  279. return false;
  280. }
  281. public override void SetValue(object component, object value)
  282. {
  283. m_Property.Value = value;
  284. }
  285. public override TypeConverter Converter
  286. {
  287. get
  288. {
  289. return m_Property.Converter;
  290. }
  291. }
  292. public override Type PropertyType
  293. {
  294. get { return m_Property.Value.GetType(); }
  295. }
  296. public override object GetEditor(Type editorBaseType)
  297. {
  298. return m_Property.Editor==null? base.GetEditor(editorBaseType):m_Property.Editor;
  299. }
  300. #endregion
  301. }</span>

下面我们来看看该如何使用,我们仍然在Form_load中添加代码如下:

[csharp] view plaincopy
  1. <span style="font-size: 13px;">            PropertyManageCls pmc = new PropertyManageCls();
  2. Property pp = new Property("ID", "1", false, true);
  3. pp.Category = "基本信息";
  4. pp.DisplayName = "我的ID";
  5. pmc.Add(pp);
  6. propertyGrid1.SelectObject=pmc;</span>
[csharp] view plain copy
  1. <span style="font-size: 13px;" data-filtered="filtered">            PropertyManageCls pmc = new PropertyManageCls();
  2. Property pp = new Property("ID", "1", false, true);
  3. pp.Category = "基本信息";
  4. pp.DisplayName = "我的ID";
  5. pmc.Add(pp);
  6. propertyGrid1.SelectObject=pmc;</span>

显示结果:

我们可以看到上面的属性显示很简单,如果想要自定义一个下拉框,或者有一个路径选择的该怎么办呢。

1)类型转换器

要实现下拉框的方法:使用类型转换器,需要继承与TypeConverter或者StringConverter,然后重写方法,代码如下:

[csharp] view plaincopy
  1. <span style="font-size: 13px;">    //下拉框类型转换器
  2. public class DropDownListConverter : StringConverter
  3. {
  4. object[] m_Objects;
  5. public DropDownListConverter(object[] objects)
  6. {
  7. m_Objects = objects;
  8. }
  9. public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
  10. {
  11. return true;
  12. }
  13. public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
  14. {
  15. return true;</span><span style='color: rgb(0, 130, 0); line-height: 15.39px; font-family: Consolas, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; font-size: 14px;'>//true下拉框不可编辑</span><span style="font-size: 13px;">
  16. </span><span style="font-size: 13px;">
  17. }
  18. public override
  19. System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
  20. {
  21. return new StandardValuesCollection(m_Objects);//我们可以直接在内部定义一个数组,但并不建议这样做,这样对于下拉框的灵活             //性有很大影响
  22. }
  23. }</span>
[csharp] view plain copy
  1. <span style="font-size: 13px;" data-filtered="filtered">    //下拉框类型转换器
  2. public class DropDownListConverter : StringConverter
  3. {
  4. object[] m_Objects;
  5. public DropDownListConverter(object[] objects)
  6. {
  7. m_Objects = objects;
  8. }
  9. public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
  10. {
  11. return true;
  12. }
  13. public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
  14. {
  15. return true;</span><span style="font-family:Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;font-size:14px;color:#0820;line-height: 15.39px;" data-filtered="filtered">//true下拉框不可编辑</span><span style="font-size: 13px;" data-filtered="filtered">
  16. </span><span style="font-size: 13px;" data-filtered="filtered">
  17. }
  18. public override
  19. System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
  20. {
  21. return new StandardValuesCollection(m_Objects);//我们可以直接在内部定义一个数组,但并不建议这样做,这样对于下拉框的灵活             //性有很大影响
  22. }
  23. }</span>

我们实现了下拉框类型转换器,但该如何使用呢?

使用方法一:我们仍然以Station类作为例子,在属性上方添加标记[TypeConverter(typeof(DropDownListConverter))],但在这种情况下,我们需要预先在DropDownListConverter中定义下拉框内容。

使用方法二:这种方法我们可以在外部定义数组,使用方便,使用方法代码如下:

[csharp] view plaincopy
  1. <span style="color: rgb(51, 51, 51); font-family: Arial;"><span style="font-size: 13px;">        private void Form_load(object sender, EventArgs e)
  2. {
  3. PropertyManageCls pmc = new PropertyManageCls();
  4. string []s=new string[] { "1", "2", "3", "4" };
  5. Property pp = new Property(txtname.Text,txtvalue.Text, false, true);
  6. pp.Category = "基本信息";
  7. pp.DisplayName = "我的ID";
  8. pp.Converter = new DropDownListConverter(s);//Property的Converter属性就可以设置类型转换
  9. pmc.Add(pp);
  10. propertyGrid1.SelectObject = pmc;
  11. }</span></span>
[csharp] view plain copy
  1. <span style="font-family:Arial;color:#333333;" data-filtered="filtered"><span style="font-size: 13px;" data-filtered="filtered">        private void Form_load(object sender, EventArgs e)
  2. {
  3. PropertyManageCls pmc = new PropertyManageCls();
  4. string []s=new string[] { "1", "2", "3", "4" };
  5. Property pp = new Property(txtname.Text,txtvalue.Text, false, true);
  6. pp.Category = "基本信息";
  7. pp.DisplayName = "我的ID";
  8. pp.Converter = new DropDownListConverter(s);//Property的Converter属性就可以设置类型转换
  9. pmc.Add(pp);
  10. propertyGrid1.SelectObject = pmc;
  11. }</span></span>

效果图:

2)属性编辑器

使用属性编辑器实现路径选择:属性编辑器需要继承与UITypeEditor

[csharp] view plaincopy
  1. <span style="font-size: 13px;">//文件路径选择                                                                                                                       public class PropertyGridFileItem : UITypeEditor
  2. {
  3. public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
  4. {
  5. return UITypeEditorEditStyle.Modal;
  6. }
  7. public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.
  8. IServiceProvider provider, object value)
  9. {
  10. IWindowsFormsEditorService edSvc =
  11. (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
  12. if (edSvc != null)
  13. {
  14. // 可以打开任何特定的对话框
  15. OpenFileDialog dialog = new OpenFileDialog();
  16. dialog.AddExtension = false;
  17. if (dialog.ShowDialog().Equals(DialogResult.OK))
  18. {
  19. return dialog.FileName;
  20. }
  21. }
  22. return value;
  23. }
  24. }</span>
[csharp] view plain copy
  1. <span style="font-size: 13px;" data-filtered="filtered">//文件路径选择                                                                                                                       public class PropertyGridFileItem : UITypeEditor
  2. {
  3. public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
  4. {
  5. return UITypeEditorEditStyle.Modal;
  6. }
  7. public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.
  8. IServiceProvider provider, object value)
  9. {
  10. IWindowsFormsEditorService edSvc =
  11. (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
  12. if (edSvc != null)
  13. {
  14. // 可以打开任何特定的对话框
  15. OpenFileDialog dialog = new OpenFileDialog();
  16. dialog.AddExtension = false;
  17. if (dialog.ShowDialog().Equals(DialogResult.OK))
  18. {
  19. return dialog.FileName;
  20. }
  21. }
  22. return value;
  23. }
  24. }</span>

使用方法一:以Station类为例,在属性上方添加标记[EditorAttribute(typeof(PropertyGridFileItem),

typeof(System.Drawing.Design.UITypeEditor))],然后将PropertyGrid的SelectObject等于Station实例就可以了;

使用方法二:使用方法代码如下:

[csharp] view plaincopy
  1. <span style="font-size: 13px;">        private void Form_load(object sender, EventArgs e)
  2. {
  3. PropertyManageCls pmc = new PropertyManageCls();
  4. Property pp = new Property(txtname.Text,txtvalue.Text, false, true);
  5. pp.Category = "基本信息";
  6. pp.DisplayName = "我的ID";
  7. pp.Editor= new PropertyGridFileItem();//Property的Editor属性就可以设置属性编辑
  8. pmc.Add(pp);
  9. propertyGrid1.SelectObject = pmc;
  10. }</span>
[csharp] view plain copy
  1. <span style="font-size: 13px;" data-filtered="filtered">        private void Form_load(object sender, EventArgs e)
  2. {
  3. PropertyManageCls pmc = new PropertyManageCls();
  4. Property pp = new Property(txtname.Text,txtvalue.Text, false, true);
  5. pp.Category = "基本信息";
  6. pp.DisplayName = "我的ID";
  7. pp.Editor= new PropertyGridFileItem();//Property的Editor属性就可以设置属性编辑
  8. pmc.Add(pp);
  9. propertyGrid1.SelectObject = pmc;
  10. }</span>

效果图如下:

通过以上方法我们可以满足一些基本需求想要了解更多,可以看以下链接:

PropertyGrid控件心得

http://blog.csdn.net/luyifeiniu/article/details/5426960#创建 PropertyGrid 控件

Customized display of collection data in a PropertyGrid

http://www.codeproject.com/KB/tabs/customizingcollectiondata.aspx

TypeConverter的层次结构

http://msdn.microsoft.com/en-us/library/8cexyz1e

关于PropertyGrid中属性的值动态从数据库取出

http://topic.csdn.net/u/20100827/11/5524219a-4457-4921-b8f2-b4c63bc6b016.html

动态可订制属性的 PropertyGrid

http://blog.csdn.net/akron/article/details/2750566

转自http://blog.csdn.net/lxping1012/article/details/7073944

C#自定义PropertyGrid属性相关推荐

  1. 自定义 Layer 属性的动画

    默认情况下,CALayer 及其子类的绝大部分标准属性都可以执行动画,无论是添加一个 CAAnimation 到 Layer(显式动画),亦或是为属性指定一个动作然后修改它(隐式动画). 但有时候我们 ...

  2. Android自定义XML属性以及遇到的命名空间的问题

    转载请注明出处:http://www.cnblogs.com/kross/p/3458068.html 最近在做一些UI,很蠢很蠢的重复写了很多代码,比如一个自定义的UI Tab,由一个ImageVi ...

  3. android自定义组件属性,android自定义控件并添加属性的方法以及示例

    安卓系统为我们提供了丰富的控件,但是在实际项目中我们仍然需要重新通过布局来实现一些效果,比如我们需要一个上面图标,下面文字的button,类似于下面这样的: 最直接的解决办法是通过将imageview ...

  4. WCF 中序列化自定义依赖属性类

    众所周知.NetFramework中存在着两种依赖属性,他们也分别集成着不同但名称相同的依赖对象: System.Windows.DependencyProperty:System.Windows.D ...

  5. android自定义控件是一个 内部类 如何在xml中引用,android 自定义view属性

    android 自定义view属性 一个完美的自定义控件也可以添加xml来配置属性和风格.要实现这一点,可按照下列步骤来做: 1) 添加自定义属性到xml文件中 2) 在xml的中,指定属性的值 3) ...

  6. 201506230818_《JavaScript权威指南(第六版)——callee和caller、对象属性用作实参、自定义函数属性》(P175-180)...

    1. callee 正在执行的函数.使用方法:arguments.callee... caller 正在调用执行函数的函数. 2.对象属性用作实参,形如:function fn(arg) { var ...

  7. 从零开始学前端:中括号代替点操作,获取对象,自定义标签属性 --- 今天你学习了吗?(JS:Day3)

    从零开始学前端:程序猿小白也可以完全掌握!-今天你学习了吗?(JS) 复习:从零开始学前端:初识函数,合法属性与自定义属性 - 今天你学习了吗?(JS:Day2) 文章目录 从零开始学前端:程序猿小白 ...

  8. 根据自定义类属性导出Excel

    根据自定义类属性导出Excel 之前的工作中遇到了导出Excel的功能需求,为了方便之后的工作使用,整理成一个Util Jar包下载 https://download.csdn.net/downloa ...

  9. 安卓自定义XML属性attrs

    attrs看字面意思就是一组属性的集合,那attrs有什么用呢,在自定义View的时候,一般会自定义一些属性,通过构造方法中AttributeSet参数的封装,让我们能够获取到为View配置的属性.( ...

最新文章

  1. 浏览器内核Trident/Gecko/WebKit/Presto
  2. Centos8中恢复根目录为默认权限
  3. 什么是维度诅咒?如何评估降维算法在当前任务数据集上的效果?
  4. mongodb一致性协议_mongodb副本集用一致性快照方法添加从节点步骤
  5. python 函数参数_python之函数(二)——函数参数详解
  6. STM32 ADC采样使用内部参考电压
  7. hadoop中unhealthynodes的问题解决
  8. 分治法在二叉树遍历中的应用(JAVA)--二叉查找树高度、前序遍历、中序遍历、后序遍
  9. 通过反射--操作运行时类中的指定的属性/方法
  10. android 编译系统make文件
  11. java高并发代码示例,Java使用代码模拟高并发操作的示例
  12. 使命召唤ol显示服务器超时,使命召唤ol网络延迟高的完整解决方案
  13. 诺基亚N9开发者模式详解:谁的N9谁做主
  14. 理财中的六大心理学效应(一)
  15. 四轴笔记----PSRAM存储器介绍
  16. Kong 网关 | Rate Limiting 限流
  17. SpringBoot(2.1.1)本地事物管理和分布式事物管理(五)
  18. Java反射获取类,方法
  19. hdu2197 本源串
  20. Django--request 对象

热门文章

  1. 打印机 欧姆龙环防伪
  2. (源码+数据库)springboot小型命题系统 毕业设计 011508
  3. ParserError Expected identifier got LParen
  4. 简单的通讯录管理系统(linux C)
  5. 服务器不停地显示线缆已拔出,插头已从插孔中拔出一直弹出是什么问题?
  6. 跟上时代步伐的慢直播神器MZB01发布
  7. NLP-Beginner 任务五:基于神经网络的语言模型+pytorch
  8. WIN7下QQ概念版使用手记
  9. Tensorflow 2.x(keras)源码详解之第九章:模型训练和预测的三种方法(fittf.GradientTapetrain_steptf.data)
  10. 《轩辕剑4》流程攻略