默认情况C#会在PropertyGrid中按照Alphabetical的规则对Category进行排序

public class Person
{[Category("Score"), DisplayName("English")]public int English { get; set; } = 115;[Category("Score"), DisplayName("Chinese")]public int Chinese { get; set; } = 100;[Category("Score"), DisplayName("Math")]public int Math { get; set; } = 98;[Category("Info"), DisplayName("Name")]public string Name { get; set; } = "Jack";[Category("Info"), DisplayName("Sex")]public string Sex { get; set; } = "Male";[Category("Info"), DisplayName("Age")]public int Age { get; set; } = 15;
}


可以看到类中定义的Score是在Info前面的,但实际Score显示在Info之后。

可以通过以下三种方式实现按照类的定义顺序进行显示(即Score显示在Info之前):

1、在每个Category前面使用A — Z的字母或者0 — 9数字进行标识进行标识。

缺点:
a.分类超过26个(使用字母)或10个(使用数字),排序就会紊乱。例如1,10,11,2,3,…9 !

b.如果调整顺序或者中间插入新的Category需要变动其他Category名称,工作量大!

2、通过在Category前插入'\t'转义字符。

    public class Person{//排在前面的Category的'\t'格数需要比后面的多//转义字符控件会自动去除(如果没有自动去除,将PropertyGrid的UseCompatibleTextRendering属性设置为true[Category("\t\tScore"), DisplayName("English")]public int English { get; set; } = 115;[Category("\t\tScore"), DisplayName("Chinese")]public int Chinese { get; set; } = 100;[Category("\t\tScore"), DisplayName("Math")]public int Math { get; set; } = 98;[Category("\tInfo"), DisplayName("Name")]public string Name { get; set; } = "Jack";[Category("\tInfo"), DisplayName("Age")]public int Age { get; set; } = 15;[Category("\tInfo"), DisplayName("Sex")]public string Sex { get; set; } = "Male";}


缺点:
a.'\t’转义字符不直观,容易遗漏或者混乱。
b.如果调整顺序或者中间插入新的Category需要变动其他Category名称,工作量大!

3、通过给对应类型加注TypeConverter属性标识实现(Converter内部利用反射,将方式2的步骤自动实现)。

    //加注一行该属性即可[TypeConverter(typeof(CategoriesSortedByClassDefinitionConverter))]//如果需要Category下的元素也按照类定义排序使用下面一行//[TypeConverter(typeof(CategoriesSortedByClassDefinitionConverter)),CategoriesSortedByClassDefinitionConverter.ElementsSameOrder]public class Person{[Category("Score"), DisplayName("English")]public int English { get; set; } = 115;[Category("Score"), DisplayName("Chinese")]public int Chinese { get; set; } = 100;[Category("Score"), DisplayName("Math")]public int Math { get; set; } = 98;[Category("Info"), DisplayName("Name")]public string Name { get; set; } = "Jack";[Category("Info"), DisplayName("Age")]public int Age { get; set; } = 15;[Category("Info"), DisplayName("Sex")]public string Sex { get; set; } = "Male";}

CategoriesSortedByClassDefinitionConverter代码:

    /// <summary>///1.设置PropertyGrid的PropertySort为Categorized或者CategorizedAlphabetical///2.要排序的类加注该属性[TypeConverter(typeof(PropertiesSortedByClassDefinitionConverter))]///3.如果需要Category下的元素也按照类定义排序,使用[TypeConverter(typeof(CategoriesSortedByClassDefinitionConverter)),CategoriesSortedByClassDefinitionConverter.ElementsSameOrder]/// </summary>public class CategoriesSortedByClassDefinitionConverter : ExpandableObjectConverter{/// <summary>///原本以为PropertySort属性为Categorized而不是CategorizedAlphabetical的话,Category下的属性会按照类定义排序。///测试时发现好像有时候还是会乱序。/// </summary>[AttributeUsage(AttributeTargets.Class)]public class ElementsSameOrderAttribute : Attribute{public bool IsSameOrder { get; set; } = true;public ElementsSameOrderAttribute(bool isSameOrder = true){IsSameOrder = isSameOrder;}}public override bool GetPropertiesSupported(ITypeDescriptorContext context){return true;}public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes){PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);var categoryNames = new List<string>();for (int i = 0; i < pdc.Count; i++){categoryNames.Add(pdc[i].Category.Replace("\t", ""));}categoryNames = categoryNames.Distinct().ToList();var propertyNames = new List<string>();for (int i = 0; i < pdc.Count; i++){propertyNames.Add(pdc[i].Name);//反射更改每个Category的名字达到效果SetValue(pdc[i], "category", pdc[i].Category.PadLeft(pdc[i].Category.Length + categoryNames.Count - categoryNames.IndexOf(pdc[i].Category), '\t'));}//判断是否强制Category中的元素按照类的定义顺序进行排布bool bElementShouldSort = false;var contextAttrList = TypeDescriptor.GetAttributes(value).OfType<ElementsSameOrderAttribute>()?.ToList();for (int i = 0; i < contextAttrList.Count; i++){if (contextAttrList[i] is ElementsSameOrderAttribute element){bElementShouldSort = element.IsSameOrder;}}return bElementShouldSort ? pdc.Sort(propertyNames.ToArray()) : pdc;}private void SetValue(object self, string fieldName, object value){Type type = self.GetType();while (type != typeof(object)){var fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();var targetField = fields.Find(n => n.Name == fieldName || n.Name == $"<{fieldName}>k__BackingField");if (targetField != null){targetField.SetValue(self, value);break;}type = type.BaseType;}}}

仅仅需要在类定义前加注一行[TypeConverter(typeof(CategoriesSortedByClassDefinitionConverter))]即可!

原本以为PropertySort属性为Categorized而不是CategorizedAlphabetical的话,Category下的属性会按照类定义排序。使用中发现好像有时候还是会乱序!

如果想要Category下的属性元素也按照类定义进行排序,在类定义前使用
[TypeConverter(typeof(CategoriesSortedByClassDefinitionConverter)),CategoriesSortedByClassDefinitionConverter.ElementsSameOrder]

多的CategoriesSortedByClassDefinitionConverter.ElementsSameOrder是用来判断是否对元素进行强制排序的,不加的话和上面一样,仅仅对目录进行强制排序。

如何让C#的PropertyGrid的Category按照类的定义顺序进行排序?相关推荐

  1. Category(分类/类目)、Protocol(协议)、Extension(扩展/延展)

    Category(分类/类目): 利用Objective-C的动态运行时分配机制,Category提供了一种比继承更为简洁的方法来对class进行扩展,无需创建对象类的子类就能为现有的类添加新方法,可 ...

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

    最近在做表单设计器,设计器上的控件都是我们自己封装的,但每个属性类别里的属性是按照属性的拼音排序的,现在想按照PropertyIndex标识进行排序(PropertyIndex的后三位是用来标识编辑器 ...

  3. Objective C 类别(Category)与类扩展(Extensions)

    一.类别(Category) 类别(Category)是一种可以为现有的类(包括类簇:NSString...,甚至源码无法获得的类)添加新方法的方式无需从现有的类继承子类.类别添加的新方法可以被子类继 ...

  4. linux内核那些事之用户空间管理

    内核主要数据结构 linux内核将用户空间抽象成struct vm_area_struct进行管理,每申请以个用户空间在内核中都会抽象成对应的vm_are_struct进行管理,同时为了区别不同进程的 ...

  5. oracle11 aud,oracle11g AUD$维护

    SYSTEM表空间使用率达到了85%,查出是用来记录审计记录的aud$表占用了很大的空间. 备份后truncate掉AUD$,问题临时解决.记得oracle11.2可以把aud$迁移到普通的表空 间. ...

  6. [转载]C# PropertyGrid控件应用心得

    最近碰到关于PropertyGrid控件,以前没有使用过,在网上找了一篇不错的文章,转来分享一下!建议查看原文章! 原文链接:http://blog.csdn.net/luyifeiniu/artic ...

  7. Winform PropertyGrid使用方法

    原文连接 先来转一个基础的,源自msdn http://www.microsoft.com/taiwan/msdn/library/2002/Jul-2002/article/usingpropgri ...

  8. C# PropertyGrid 简单使用

    目录 一. 导入数据 二. PropertyGrid 的简单属性配置 三. 设置字段属性 四. 字段的下拉框 五. 多级展开 六. 显示内容的排序 6.1 属性排序 6.1.1 自定义排序 6.1.2 ...

  9. c#中PropertyGrid 控件简介

    PropertyGrid 控件简介 如果您使用过 Microsoft® Visual Basic® 或 Microsoft Visual Studio .NET,那么您一定使用过属性浏览器来浏览.查看 ...

最新文章

  1. 推荐几个微信Markdown排版工具
  2. Windows Phone 7 Tips “.NET研究”(4)
  3. COOKIE和SESSION关系和区别
  4. grep命令參数及使用方法
  5. [zz]volatile
  6. 动态加载类的原理——元数据的使用
  7. 多项目Node版本控制
  8. python 趋势跟踪算法_DualThrust区间突破策略Python版
  9. 16. Segmentation
  10. convolution backbone network——Deep Pyramidal Residual Networks
  11. 今天nba预测分析_NBA情报预测分析_NBA足球俱乐部 - 全球体育网
  12. Unity实战之王者荣耀段位计算
  13. 走对路!在智能时代别捡了芝麻丢了西瓜!
  14. [NOIP2003提高组]侦探推理
  15. Python函数随机种子random_state
  16. 人大金仓受邀参加《航天七〇六“我与航天电脑有约”全国合作伙伴大会》
  17. 全球三效催化剂回收行业调研及趋势分析报告
  18. mysql商品表_(三)购物商城数据库设计-商品表DDL(Mysql)
  19. 材料进步使新一代功率电感器_凯利讯半导体
  20. 电子琴仿真c语言程序,基于单片机简易电子琴仿真和源程序

热门文章

  1. IDEA设置打开窗口的数量
  2. mysql 表转置,数据转置,让行列转换变的如此简单
  3. pbootcms节日礼品窗花泥塑工艺画类网站模板
  4. ODOO13 如何在Many2one字段选择控件上进行多条件搜索
  5. java提高篇(44)--XML语言
  6. 基于@vue-cli3的多页面应用改造及nignx配置
  7. SoundTouch音频处理库的简单使用(音调、音速、声道等等)
  8. AndroidStudio创建jniLibs文件夹添加jar包\so库
  9. 机器学习系列手记(七):优化算法之随机梯度下降法
  10. 万字总结数据库Redis,值得大家收藏