zl程序教程

您现在的位置是:首页 >  其他

当前栏目

PropertyGrid控件 分类(Category)及属性(Property)排序

属性排序 控件 分类 Property Category
2023-09-14 09:02:13 时间
最近在做表单设计器,设计器上的控件都是我们自己封装的,但每个属性类别里的属性是按照属性的拼音排序的,现在想按照PropertyIndex标识进行排序(PropertyIndex的后三位是用来标识编辑器的)。 具体实现如下: using System; using System.Collections.Generic; using System.Text; using System.Ref

最近在做表单设计器,设计器上的控件都是我们自己封装的,但每个属性类别里的属性是按照属性的拼音排序的,现在想按照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

 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;
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) 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; #endregion abEvent = 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; #endregion else 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

 return indexCode;

 indexCode = value;

 /// summary 

 /// 

 /// /summary 

 /// param name="indexCode" /param 

 public PropertyIndexAttribute(string indexCode)

 this.indexCode = indexCode;

 }
排序部分:

 #region Helper Class - PropertyOrderPair

 public class PropertyOrderPair : IComparable

 private int _order;

 private string _name;

 public string Name

 return _name;

 private PropertyDescriptor _property;

 public PropertyDescriptor Property

 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

 return this.BaseTextEdit.Properties.Mask.MaskType;

 this.BaseTextEdit.Properties.Mask.MaskType = value;


[DisplayName("忽略空白")] [Description("对于 Simple、Regular 和 RegEx 掩码类型,MaskProperties.IgnoreMaskBlank 属性是有效的。 如果此属性值设置为 true,那么空白编辑器会失去焦点。 如果编辑器的取值仅部分完成,那么焦点不能被移出此编辑器,直至最终用户输入了完整的取值或者通过清除编辑器框而清除了取值。 如果此属性值设置为 false,那么焦点不能移出此编辑器,直至完整输入取值。 ")] [PropertyIndex("103006000")] public bool IgnoreMaskBlank return this.BaseTextEdit.Properties.Mask.IgnoreMaskBlank; 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 return this.BaseTextEdit.Properties.Mask.PlaceHolder; this.BaseTextEdit.Properties.Mask.PlaceHolder = value; [Category("掩码")] [Browsable(true)] [DisplayName("错误提示音")] [Description("对于所有类型的掩码,Boolean 型的 MaskProperties.BeepOnError 属性都是可用的。 把此属性设置为 true,当最终用户试图键入一个无效字符串时允许响铃。 假定使用了 Numeric 类型的掩码。 在这种情况下,最终用户每次试图键入非数字字符时,编辑器都将发出一段提示声音。")] [PropertyIndex("103005000")] public bool BeepOnError return this.BaseTextEdit.Properties.Mask.BeepOnError; this.BaseTextEdit.Properties.Mask.BeepOnError = value;
[DisplayName("自动填充")] [Description("对于 RegEx 掩码类型,可以启用自动完成功能。 在这种模式中,编辑器将尝试完成已经由最终用户部分输入的取值。")] [PropertyIndex("103004000")] public DevExpress.XtraEditors.Mask.AutoCompleteType AutoComplete return this.BaseTextEdit.Properties.Mask.AutoComplete; 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 return this.BaseTextEdit.Properties.Mask.SaveLiteral; this.BaseTextEdit.Properties.Mask.SaveLiteral = value; [Category("掩码")] [Browsable(true)] [DisplayName("掩码字符串")] [Description("掩码字符串标识了数据输入模板。 可以使用预定义的掩码字符串,或者构建自己的掩码表达式, 应该根据掩码类型来设置掩码字符串。")] [PropertyIndex("103002000")] public string EditMask return this.BaseTextEdit.Properties.Mask.EditMask; 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 return this.BaseTextEdit.Properties.Mask.ShowPlaceHolders; 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;


控件中的使用:



效果:


完成!



WPF - Group分组对ListBox等列表样式的约束 原文:WPF - Group分组对ListBox等列表样式的约束 在做WPF主题支持时,出现一个分组引起的莫名错误,可是折腾了我一番。在没有使用样式时,列表分组很正常,使用了别人写的ListBox列表样式后,发现GroupItem分组区没有内容,是空的,本篇把这一问题的解决过程给大家说一下,做主题时可以注意分组对列表样式的限制了。
easyUI 中datagrid 返回列隐藏方法 easyui的datagrid方法返回的列,有的值不需要显示可以使用hidden(属性进行隐藏)   columns : [ [{ field : bailClass , title : 类别 ,
在Qt之QSS(样式表语法)一节讲过关于“设置对象属性”的用法,里面有一条很重要的原则是:任何可被识别的Q_PROPERTY都可以使用qproperty-语法设置。 这里需要对Qt属性系统有一定的了解,详见:Qt之属性系统。