PropertyGrid控件 分类(Category)及属性(Property)排序
生活随笔
收集整理的這篇文章主要介紹了
PropertyGrid控件 分类(Category)及属性(Property)排序
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在做表單設計器,設計器上的控件都是我們自己封裝的,但每個屬性類別里的屬性是按照屬性的拼音排序的,現在想按照PropertyIndex標識進行排序(PropertyIndex的后三位是用來標識編輯器的)。
具體實現如下:
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.ComponentModel; using HC.Test.ComponentModel; using HC.Test.Common; using System.Data; using HC.Test.Common.ComponentModel; using System.Xml.Serialization; using System.Windows.Forms; using HC.Test.Forms.ControlConfig; using System.Collections;namespace HC.Test.Designer.UI {public class ControlEditorTypeDescriptionProvider : TypeDescriptionProvider{protected TypeDescriptionProvider _baseProvider;private PropertyDescriptorCollection _propCache;protected Dictionary<Type, Type> dictEdtor;/// <summary>/// 屬性Editor字典/// Key:Attribute Value:Editor/// </summary>public Dictionary<Type, Type> EdtorDictionary{get{return dictEdtor;}}public ControlEditorTypeDescriptionProvider(): base(){dictEdtor = new Dictionary<Type, Type>();}/// <summary>/// /// </summary>/// <param name="t">要修改屬性的基類</param>public ControlEditorTypeDescriptionProvider(Type t): this(){_baseProvider = TypeDescriptor.GetProvider(t);}public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance){PropertiesTypeDescriptor typeDes = new PropertiesTypeDescriptor(_baseProvider.GetTypeDescriptor(objectType, instance), this, objectType);return typeDes;}}/// <summary>/// 屬性集合的描述/// </summary>public class PropertiesTypeDescriptor : CustomTypeDescriptor{private Type objType;private DataTable dtConfig = new DataTable();private ControlEditorTypeDescriptionProvider provider;public PropertiesTypeDescriptor(ICustomTypeDescriptor descriptor, ControlEditorTypeDescriptionProvider provider, Type objType): base(descriptor){if (provider == null){throw new ArgumentNullException("provider");}if (descriptor == null){throw new ArgumentNullException("descriptor");}if (objType == null){throw new ArgumentNullException("objectType");}this.objType = objType;this.provider = provider;}/// <summary>/// 獲取屬性列表/// </summary>/// <param name="attributes"></param>/// <returns></returns>public override PropertyDescriptorCollection GetProperties(Attribute[] attributes){try{string nowIndexCode = "";Type editor;Type editorControl;Attribute abEvent;EventPropertyDescriptor des;bool showPageSize = true;//從dll中讀取配置Dictionary<string, ControlEditorType> dictConfig = PubFunc.GetPropertyEditor();ArrayList orderedProperties = new ArrayList();foreach (PropertyDescriptor prop in base.GetProperties(attributes)){ #region 控件、表單部分屬性屏蔽//屏蔽所有控件數據Category 數據 屬性if (((System.ComponentModel.MemberDescriptor)(prop)).Category == "數據" || ((System.ComponentModel.MemberDescriptor)(prop)).Category == "Data"){continue;}//屏蔽所有控件數據Category 雜項 屬性if (((System.ComponentModel.MemberDescriptor)(prop)).Category == "雜項" || ((System.ComponentModel.MemberDescriptor)(prop)).Category == "Misc"){continue;}#endregion#region 屏蔽不需要顯示的屬性switch (((System.ComponentModel.MemberDescriptor)(prop)).Name){case "DisplayStyleEnum":CommonHelpDisplayStyleEnum displayType = (CommonHelpDisplayStyleEnum)prop.GetValue(this);if (displayType == CommonHelpDisplayStyleEnum.TreeStyle){showPageSize = false;}break;case "PageSize":if (!showPageSize){continue;}break;}#endregionabEvent = prop.Attributes[typeof(PropertyIndexAttribute)];if (abEvent != null && abEvent is PropertyIndexAttribute){nowIndexCode = ((PropertyIndexAttribute)abEvent).IndexCode;#region 事件編輯器處理if (nowIndexCode.Length > 6){//最后三位000標識 不帶編輯器if (nowIndexCode.Substring(6, 3) == "000"){orderedProperties.Add(new PropertyOrderPair(prop.DisplayName, int.Parse(nowIndexCode), prop));continue;}foreach (var cet in dictConfig){if (cet.Key == nowIndexCode.Substring(6, 3)){//根據配置文件的序列號,獲取出全名HC.Test.Designer.UI.EventActionEditorControl,放入下面的函數中 editorControl = ReflectionActivator.GetType("HC.Test.Designer.UI", cet.Value.EditorName);if (editorControl == null){orderedProperties.Add(new PropertyOrderPair(prop.DisplayName, int.Parse(nowIndexCode), prop));break;}if (cet.Value.EditorType == "CommonTypeDropDownEditor"){editor = ReflectionActivator.GetGenericType("HC.Test.Common.Design", "HC.Test.Common.Design.GenericDropDownControlEditor`1", new Type[] { editorControl });}else{editor = ReflectionActivator.GetGenericType("HC.Test.Common.Design", "HC.Test.Common.Design.ModalFormEditor`1", new Type[] { editorControl });}des = new EventPropertyDescriptor(prop, editor);orderedProperties.Add(new PropertyOrderPair(prop.DisplayName, int.Parse(nowIndexCode), des));break;}}}#endregionelse{orderedProperties.Add(new PropertyOrderPair(prop.DisplayName, 0, prop));continue;}}else{orderedProperties.Add(new PropertyOrderPair(prop.DisplayName, 0, prop));}}//屬性集合按照PropertyIndexAttribute及DisplayName排序orderedProperties.Sort();PropertyDescriptorCollection propsTemp = new PropertyDescriptorCollection(null);foreach (PropertyOrderPair pop in orderedProperties){propsTemp.Add(pop.Property);}return propsTemp;//ArrayList propertyNames = new ArrayList();//foreach (PropertyOrderPair pop in orderedProperties)//{// propertyNames.Add(pop.Name);//}//return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));}catch{throw;}}}/// <summary>/// 屬性 描述(屬性的屬性)/// </summary>public class EventPropertyDescriptor : PropertyDescriptor{Type editor = null;PropertyDescriptor prop;public EventPropertyDescriptor(PropertyDescriptor descr, Type editor): base(descr){this.prop = descr;this.editor = editor; }/// <summary>/// 獲取Editor;/// </summary>/// <param name="editorBaseType"></param>/// <returns></returns>public override object GetEditor(Type editorBaseType){object obj = base.GetEditor(editorBaseType);if (obj == null){obj = ReflectionActivator.CreateInstace(editor);}return obj;}public override bool CanResetValue(object component){return prop.CanResetValue(component);}public override Type ComponentType{get { return prop.ComponentType; }}public override object GetValue(object component){return prop.GetValue(component);}public override bool IsReadOnly{get { return prop.IsReadOnly; }}public override Type PropertyType{get { return prop.PropertyType; }}public override void ResetValue(object component){prop.ResetValue(component);}public override void SetValue(object component, object value){prop.SetValue(component, value);}public override bool ShouldSerializeValue(object component){return prop.ShouldSerializeValue(component);}}}PropertyIndexAttribute類:
/// <summary>/// 屬性信息的順序分類等信息/// 字段或者屬性等 可序列化的信息上/// 現在是一共9位,最后3位用來標識編輯器 最后三位000 默認不會識別編輯器/// 中間三位用來屬性排序/// </summary>[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]public class PropertyIndexAttribute : Attribute{private string indexCode;/// <summary>/// 標識/// </summary>public string IndexCode{get{return indexCode;}set{indexCode = value;}}/// <summary>/// /// </summary>/// <param name="indexCode"></param>public PropertyIndexAttribute(string indexCode){this.indexCode = indexCode;}}排序部分:
#region Helper Class - PropertyOrderPairpublic class PropertyOrderPair : IComparable{private int _order;private string _name;public string Name{get{return _name;}}private PropertyDescriptor _property;public PropertyDescriptor Property{get{return _property;}}public PropertyOrderPair(string name, int order, PropertyDescriptor property){_order = order;_name = name;_property = property;}public int CompareTo(object obj){//// Sort the pair objects by ordering by order value// Equal values get the same rank//int otherOrder = ((PropertyOrderPair)obj)._order;if (otherOrder == _order){//// If order not specified, sort by name//string otherName = ((PropertyOrderPair)obj)._name;return string.Compare(_name, otherName);}else if (otherOrder > _order){return -1;}return 1;}}#endregion#region Helper Class - PropertyOrderAttribute 未用//[AttributeUsage(AttributeTargets.Property)]//public class PropertyOrderAttribute : Attribute//{// //// // Simple attribute to allow the order of a property to be specified// //// private int _order;// public PropertyOrderAttribute(int order)// {// _order = order;// }// public int Order// {// get// {// return _order;// }// }//}#endregion設置PropertyGrid控件的屬性:
用法:
為每個屬性添加屬性:[PropertyIndex("103001000")]
比如:
[Category("掩碼")][Browsable(true)][DisplayName("掩碼類型")]//[Description("設置執行單擊事件的快捷鍵")][PropertyIndex("103001000")]public DevExpress.XtraEditors.Mask.MaskType MaskType{get{return this.BaseTextEdit.Properties.Mask.MaskType;}set{this.BaseTextEdit.Properties.Mask.MaskType = value;}}[Category("掩碼")][Browsable(true)][DisplayName("忽略空白")][Description("對于 Simple、Regular 和 RegEx 掩碼類型,MaskProperties.IgnoreMaskBlank 屬性是有效的。 如果此屬性值設置為 true,那么空白編輯器會失去焦點。 如果編輯器的取值僅部分完成,那么焦點不能被移出此編輯器,直至最終用戶輸入了完整的取值或者通過清除編輯器框而清除了取值。 如果此屬性值設置為 false,那么焦點不能移出此編輯器,直至完整輸入取值。 ")][PropertyIndex("103006000")]public bool IgnoreMaskBlank{get{return this.BaseTextEdit.Properties.Mask.IgnoreMaskBlank;}set{this.BaseTextEdit.Properties.Mask.IgnoreMaskBlank = value;}}[Category("掩碼")][Browsable(true)][DisplayName("格式占位符")][Description("對于 Simple、Regular 和 RegEx 掩碼類型,使用由 MaskProperties.PlaceHolder 屬性確定的特殊字符來呈現編輯框中的占位符。 可以使用該屬性來改變默認的占位符 (“_”符)。 對于 RegEx 掩碼類型,通過把 MaskProperties.ShowPlaceHolders 屬性設置為 false,可以隱藏占位符。 ")][PropertyIndex("103007000")]public char PlaceHolder{get{return this.BaseTextEdit.Properties.Mask.PlaceHolder;}set{this.BaseTextEdit.Properties.Mask.PlaceHolder = value;}}[Category("掩碼")][Browsable(true)][DisplayName("錯誤提示音")][Description("對于所有類型的掩碼,Boolean 型的 MaskProperties.BeepOnError 屬性都是可用的。 把此屬性設置為 true,當最終用戶試圖鍵入一個無效字符串時允許響鈴。 假定使用了 Numeric 類型的掩碼。 在這種情況下,最終用戶每次試圖鍵入非數字字符時,編輯器都將發出一段提示聲音。")][PropertyIndex("103005000")]public bool BeepOnError{get{return this.BaseTextEdit.Properties.Mask.BeepOnError;}set{this.BaseTextEdit.Properties.Mask.BeepOnError = value;}}[Category("掩碼")][Browsable(true)][DisplayName("自動填充")][Description("對于 RegEx 掩碼類型,可以啟用自動完成功能。 在這種模式中,編輯器將嘗試完成已經由最終用戶部分輸入的取值。")][PropertyIndex("103004000")]public DevExpress.XtraEditors.Mask.AutoCompleteType AutoComplete{get{return this.BaseTextEdit.Properties.Mask.AutoComplete;}set{this.BaseTextEdit.Properties.Mask.AutoComplete = value;}}[Category("掩碼")][Browsable(true)][DisplayName("保存格式字符串")][Description("對于 Simple 和 Regular 掩碼類型,可以指定是否總是把顯示的掩碼字符 (原義字符) 包括在編輯器的取值內。 換句話說,你可以控制那些字符是否出現在由 BaseEdit.EditValue 屬性返回的取值中。 要使這些字符無法被訪問,則必須把 MaskProperties.SaveLiteral 屬性設置為 false。 在這種情況下,如果顯示的取值是“(555)123-76-34”,那么由 BaseEdit.EditValue 屬性返回的取值就是“5551237634”。 ")][PropertyIndex("103008000")]public bool SaveLiteral{get{return this.BaseTextEdit.Properties.Mask.SaveLiteral;}set{this.BaseTextEdit.Properties.Mask.SaveLiteral = value;}}[Category("掩碼")][Browsable(true)][DisplayName("掩碼字符串")][Description("掩碼字符串標識了數據輸入模板。 可以使用預定義的掩碼字符串,或者構建自己的掩碼表達式, 應該根據掩碼類型來設置掩碼字符串。")][PropertyIndex("103002000")]public string EditMask{get{return this.BaseTextEdit.Properties.Mask.EditMask;}set{this.BaseTextEdit.Properties.Mask.EditMask = value;}}[Category("掩碼")][Browsable(true)][DisplayName("顯示格式占位符")][Description("對于 Simple、Regular 和 RegEx 掩碼類型,使用由 MaskProperties.PlaceHolder 屬性確定的特殊字符來呈現編輯框中的占位符。 可以使用該屬性來改變默認的占位符 (“_”符)。 對于 RegEx 掩碼類型,通過把 MaskProperties.ShowPlaceHolders 屬性設置為 false,可以隱藏占位符。 ")][PropertyIndex("103003000")]public bool ShowPlaceHolders{get{return this.BaseTextEdit.Properties.Mask.ShowPlaceHolders;}set{this.BaseTextEdit.Properties.Mask.ShowPlaceHolders = value;}}效果:
如果使用網絡上的sort排序代碼(感覺不對,于是沒有采用):
//ArrayList propertyNames = new ArrayList();//foreach (PropertyOrderPair pop in orderedProperties)//{// propertyNames.Add(pop.Name);//}//return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));效果如下:
本文參考:
PropertyGrid排序
Ordering Items in the Property Grid
PropertyGrid類別排序實現,可以參考:
點擊打開鏈接?
具體實現如下:
屬性控件PropertyGrid事件:
#region 屬性分組排序部分private void propertyGrid_SelectedObjectsChanged(object sender, EventArgs e){propertyGrid.Tag = propertyGrid.PropertySort;propertyGrid.PropertySort = PropertySort.CategorizedAlphabetical;propertyGrid.Paint += new PaintEventHandler(propertyGrid_Paint); }private void propertyGrid_Paint(object sender, PaintEventArgs e){var categorysinfo = propertyGrid.SelectedObject.GetType().GetField("categorys", BindingFlags.NonPublic | BindingFlags.Instance);if (categorysinfo != null){var categorys = categorysinfo.GetValue(propertyGrid.SelectedObject) as List<String>;propertyGrid.CollapseAllGridItems();GridItemCollection currentPropEntries = typeof(PropertyGrid).GetField("currentPropEntries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid) as GridItemCollection;var newarray = currentPropEntries.Cast<GridItem>().OrderBy((t) => categorys.IndexOf(t.Label)).ToArray();currentPropEntries.GetType().GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentPropEntries, newarray);propertyGrid.ExpandAllGridItems();propertyGrid.PropertySort = (PropertySort)propertyGrid.Tag;}propertyGrid.Paint -= new PaintEventHandler(propertyGrid_Paint);} 由于我用的是:
所以在反射的時候,用的是:
GridItemCollection currentPropEntries = typeof(PropertyGrid).GetField("currentPropEntries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid) as GridItemCollection; 而非參考文章中的:
GridItemCollection currentPropEntries = propertyGrid1.GetType().GetField("currentPropEntries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid1) as GridItemCollection;
控件中的使用:
效果:
完成!
總結
以上是生活随笔為你收集整理的PropertyGrid控件 分类(Category)及属性(Property)排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF自定义控件与样式(1)-矢量字体图
- 下一篇: Thread详解