源文:http://www.cnblogs.com/bicker/p/3318934.html

最近接触C#的PropertyGrid比较多,得到了两个小心得记录一下。

第1点是关于控制PropertyGrid中属性的只读属性的。

我遇到的问题是这样的,我需要在运行时根据SVN的状态动态控制PropertyGrid中的属性的读写控制。以前的做法比较简单,直接是 PropertyGrid.Enabled(false)。这样的坏处是完全使Grid完全失效,连滚动条也不可用了,不便于查看属性。后来上网查阅相关 的资料,网上有比较的是同一篇文章的复制,原文出处我已经找不到了。先把原文贴出来如下:

原文中提到的思路是在运行时,通过反射的方式修改每一个Property的ReadOnlyAttribute。只是心得那里説不很不清楚,要对整个对象而非具体的属性进行控制时怎么办。

我的第一个想法是遍历所有的Property,对每一个都设置ReadOnly,但是这样是错误的,而且有副作用。后来经过试验,我直接对PropertyGrid的Object设置ReadOnly。

两点C#的propertyGrid的使用心得【转】-LMLPHP
1 private void button1_Click(object sender, EventArgs e)
2 {
3 Type readonlyType = typeof(System.ComponentModel.ReadOnlyAttribute);
4 PropertyDescriptorCollection props = TypeDescriptor.GetProperties(propertyGrid1.SelectedObject);
5 FieldInfo fld = readonlyType.GetField("isReadOnly", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.CreateInstance);
6 AttributeCollection attrs = TypeDescriptor.GetAttributes(propertyGrid1.SelectedObject);
7 fld.SetValue(attrs[typeof(ReadOnlyAttribute)], gridReadOnly);
8 gridReadOnly = !gridReadOnly;
9 }
两点C#的propertyGrid的使用心得【转】-LMLPHP

这里説一下,在找解决办法的时候,还去顺便了解了一下c#在运行时,动态添加Attribute的内容,这个内容留下次再记录好了。

还找到一篇讲反射可以通过FieldInfo.SetValue设置任何字段的值的文章:http://www.cnblogs.com/Laser_Lu/archive/2004/08/01/29171.html

第2点是PropertyGrid中使用TypeConverter

PropertyGrid中对于自定义的类型显示支持有限,最好是自己去实现自己的TypeConverter,把类型转换来进行显示。我写了一个简单的例子,把List类型转换成string。

两点C#的propertyGrid的使用心得【转】-LMLPHP
 1 public class MyColorConverter : TypeConverter
2 {
3 public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
4 {
5 if (value == null)
6 {
7 return new List<int>();
8 }
9 string stringValue = value as string;
10 if (stringValue != null)
11 {
12 List<int> result = new List<int>();
13 string[] vs = stringValue.Split(new char[] { ',' });
14 foreach (string eachString in vs)
15 {
16 result.Add(int.Parse(eachString));
17 }
18 return result;
19 }
20 else
21 {
22 return base.ConvertFrom(context, culture, value);
23 }
24 }
25
26 public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
27 {
28 if (destinationType == typeof(string))
29 {
30 return true;
31 }
32 return base.CanConvertTo(context, destinationType);
33 }
34
35 public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes)
36 {
37 throw new Exception("The method or operation is not implemented.");
38 }
39
40 public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
41 {
42 if (destinationType == typeof(string))
43 {
44 List<int> list = value as List<int>;
45 if (list != null && list.Count > 0)
46 {
47 StringBuilder sb = new StringBuilder();
48 foreach (int v in list)
49 {
50 sb.AppendFormat("{0},", v);
51 }
52 sb.Remove(sb.Length - 1, 1);
53 return sb.ToString();
54 }
55 return "";
56 }
57 else
58 {
59 return base.ConvertTo(context, culture, value, destinationType);
60 }
61 }
62
63 public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
64 {
65 if (sourceType == typeof(string))
66 {
67 return true;
68 }
69 return base.CanConvertFrom(context, sourceType);
70 }
71 }
两点C#的propertyGrid的使用心得【转】-LMLPHP
两点C#的propertyGrid的使用心得【转】-LMLPHP
     private List<int> color1 = new List<int>();
[Category("main")]
[DisplayName("颜色1")]
[TypeConverter(typeof(MyColorConverter))]
public List<int> Color1
{
get { return color1; }
set { color1 = value; }
}
两点C#的propertyGrid的使用心得【转】-LMLPHP

ConvertFrom函数会在PropertyGrid中的字符串被修改保存后被调用

ConvertTo函数则是在最初显示PropertyGrid以及对List进行修改之后被调用

05-11 22:08