最近遇到一個項目需要使用的propertyGrid來讓用戶自定義屬性,在遇到對集合進行操作的的時候遇到幾個問題:
1.在集合編輯器上,屬性設計區域下面的沒有屬性描述區域,導致有的用戶無法知道這個屬性有啥用,如下圖
2.集合編輯器只能指定同一個類型,但有個需求是需要在一個集合里添加基於同一個基類的不同拓展的多個類型
3.需要限制集合編輯器Items的數量,不能超過指定數量.
先處理第一個問題,老規矩,遇到問題的時候先google下,結果沒找到我需要的,只能老老實實去看看源碼希望能有點收貨,運氣還好,反編譯了下CollectionEditor,發現其實
是有描述區域的,只是不知道微軟咋想的,默認是不顯示的,但是可以通過反射使其顯示,具體代碼直接貼上
1 public class ExtendCollectionEditor : CollectionEditor 2 { 3 public ExtendCollectionEditor(Type type) : base(type) 4 { 5 } 6 protected override CollectionForm CreateCollectionForm() 7 { 8 CollectionForm frm = base.CreateCollectionForm(); 9 FieldInfo fileinfo = frm.GetType().GetField("propertyBrowser", BindingFlags.NonPublic | BindingFlags.Instance); 10 if (fileinfo != null) 11 { 12 (fileinfo.GetValue(frm) as System.Windows.Forms.PropertyGrid).HelpVisible = true; 13 } 14 frm.Width = 700; 15 frm.Height = 600; 16 return frm; 17 } 18 }
下面是效果
第二個問題也是通過源碼+測試搞定,直接上代碼
1 /// <summary> 2 /// 實現多個已知對象的集合添加 3 /// </summary> 4 public class ItemCollectionEditor : ExtendCollectionEditor 5 { 6 #region MyRegion 7 public ItemCollectionEditor(Type type) : base(type) 8 { 9 } 10 11 12 protected override Type[] CreateNewItemTypes() 13 { 14 return new Type[] 15 { 16 typeof(Panel), 17 typeof(Tabs), 18 typeof(Layout) 19 }; 20 } 21 22 protected override bool CanSelectMultipleInstances() 23 { 24 return true; 25 } 26 #endregion 27 28 }
需要重寫CreateNewItemTypes和CanSelectMultipleInstances兩個方法,CreateNewItemTypes是定義允許添加的類型,CanSelectMultipleInstances是告訴設計器
是否允許添加多種實例,這里直接返回true表示允許,效果如下
第三個問題翻了半天也看到有啥屬性或方法可以滿足,只能隨便加個變量參數來處理了代碼如下.InstanceCount是用來定義已經添加在集合里的數量
1 public class SingleItemEditor : ItemCollectionEditor 2 { 3 protected int InstanceCount = 0; 4 #region MyRegion 5 public SingleItemEditor(Type type) : base(type) 6 { 7 8 } 9 10 protected override IList GetObjectsFromInstance(object instance) 11 { 12 if (InstanceCount == 0) 13 { 14 InstanceCount++; 15 return base.GetObjectsFromInstance(instance); 16 } 17 else 18 { 19 return null; 20 } 21 } 22 23 protected override object[] GetItems(object editValue) 24 { 25 InstanceCount = ((dynamic)editValue).Count; 26 return base.GetItems(editValue); 27 } 28 29 protected override void DestroyInstance(object instance) 30 { 31 InstanceCount--; 32 base.DestroyInstance(instance); 33 } 34 35 #endregion 36 37 }
以上三個問題總算全部解決,雖然第三個解決的有些不夠優雅,但是目的還算達到了
PS.一開始在添加編輯器里添加了Item后發現點確定保存后再次點擊編輯進去一個Item也沒了,后來發現對於集合屬性,必須得在要編輯的類的構造函數里先
把這個集合屬性new一個出來,因為CollectionEditor不會幫你實例化集合當沒有集合實例的時候,item當然就沒辦法添加進去了.