两点C#的propertyGrid的使用心得
最近接觸C#的PropertyGrid比較多,得到了兩個小心得記錄一下。
第1點是關于控制PropertyGrid中屬性的只讀屬性的。
我遇到的問題是這樣的,我需要在運行時根據SVN的狀態動態控制PropertyGrid中的屬性的讀寫控制。以前的做法比較簡單,直接是PropertyGrid.Enabled(false)。這樣的壞處是完全使Grid完全失效,連滾動條也不可用了,不便于查看屬性。后來上網查閱相關的資料,網上有比較的是同一篇文章的復制,原文出處我已經找不到了。先把原文貼出來如下:
大家知道在類的某個屬性中加[ReadOnlyAttribute(true)]聲明標記后,此類的對象的這個屬性在PropertyGrid中就表現為灰色不可更改,請問大家有沒有什么辦法動態地讓這個屬性在PropertyGrid中的顯示變為可讀寫么? ??
? 以下的方法試過,不好用 ??
? 1、想在程序里改聲明標記,可是不行 ??
? 2、另外寫個類,同樣的屬性標記為[ReadOnlyAttribute(false)],然后重新selectobject,可是太復雜了。???
用反射可以實現動態改變,只讀、可見等等,這些屬性都可以改變。 ??
? 以下兩個方法分別實現可見性和只讀屬性的動態改變: ??
? void ? SetPropertyVisibility(object ? obj, ? string ? propertyName, ? bool ? visible) ??
? { ??
? Type ? type ? = ? typeof(BrowsableAttribute); ??
? PropertyDescriptorCollection ? props ? = ? TypeDescriptor.GetProperties(obj); ??
? AttributeCollection ? attrs ? = ? props[propertyName].Attributes; ??
? FieldInfo ? fld ? = ? type.GetField("browsable", ? BindingFlags.Instance ? | ? BindingFlags.NonPublic); ??
? fld.SetValue(attrs[type], ? visible); ??
? } ??
? void ? SetPropertyReadOnly(object ? obj, ? string ? propertyName, ? bool ? readOnly) ??
? { ??
? Type ? type ? = ? typeof(System.ComponentModel.ReadOnlyAttribute); ??
? PropertyDescriptorCollection ? props ? = ? TypeDescriptor.GetProperties(obj); ??
? AttributeCollection ? attrs ? = ? props[propertyName].Attributes; ??
? FieldInfo ? fld ? = ? type.GetField("isReadOnly", ? BindingFlags.Instance ? | ? BindingFlags.NonPublic ? | ? BindingFlags.CreateInstance); ??
? fld.SetValue(attrs[type], ? readOnly); ??
? }
使用時,SetPropertyVisibility(obj, ? "名稱", ? true); ??
? obj指的就是你的SelectObject, ? “名稱”是你SelectObject的一個屬性 ??
? 當然,調用這兩個方法后,重新SelectObject一下,就可以了
心得:
(1)如果對屬性框中所有屬性一起進行控制,可以不添加 [ReadOnlyAttribute(false)]標記,propertyName可以是任何屬性名稱。[注:這里講得很不清楚]
(2)如果僅僅對某一個屬性進行控制,則必須在每個屬性的描述中添加 [ReadOnlyAttribute(false)]標記。propertyName必須是所要控制的屬性名。
原文中提到的思路是在運行時,通過反射的方式修改每一個Property的ReadOnlyAttribute。只是心得那里説不很不清楚,要對整個對象而非具體的屬性進行控制時怎么辦。
我的第一個想法是遍歷所有的Property,對每一個都設置ReadOnly,但是這樣是錯誤的,而且有副作用。后來經過試驗,我直接對PropertyGrid的Object設置ReadOnly。
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#在運行時,動態添加Attribute的內容,這個內容留下次再記錄好了。
還找到一篇講反射可以通過FieldInfo.SetValue設置任何字段的值的文章:http://www.cnblogs.com/Laser_Lu/archive/2004/08/01/29171.html
第2點是PropertyGrid中使用TypeConverter
PropertyGrid中對于自定義的類型顯示支持有限,最好是自己去實現自己的TypeConverter,把類型轉換來進行顯示。我寫了一個簡單的例子,把List類型轉換成string。
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 } private List<int> color1 = new List<int>();[Category("main")][DisplayName("顏色1")][TypeConverter(typeof(MyColorConverter))]public List<int> Color1{get { return color1; }set { color1 = value; }}ConvertFrom函數會在PropertyGrid中的字符串被修改保存后被調用
ConvertTo函數則是在最初顯示PropertyGrid以及對List進行修改之后被調用
轉載于:https://www.cnblogs.com/bicker/p/3318934.html
總結
以上是生活随笔為你收集整理的两点C#的propertyGrid的使用心得的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 获取FormData数据
- 下一篇: J2SE总结