属性默认按照字母顺序排序,有时,我们想要按自定义的顺序排序

这个工具类可以把每个属性类别里的属性排序,但是不能把属性类别排序。

为属性类添加属性:[TypeConverter(typeof(PropertySorter))]
为每个属性添加属性:[PropertyOrder(10)]

private void Form_Load(object sender, EventArgs e)
{
propertyGrid1.SelectedObject = new Person();
}
[TypeConverter(typeof(PropertySorter))]
[DefaultProperty("Name")]
public class Person
{
protected const string PERSONAL_CAT = "Personal Details"; private string _name = "Bob";
private DateTime _birthday = new DateTime(,,); [Category(PERSONAL_CAT), PropertyOrder()]
public string Name
{
get {return _name;}
set {_name = value;}
} [Category(PERSONAL_CAT), PropertyOrder()]
public DateTime Birthday
{
get {return _birthday;}
set {_birthday = value;}
} [Category(PERSONAL_CAT), PropertyOrder()]
public int Age
{
get
{
TimeSpan age = DateTime.Now - _birthday;
return (int)age.TotalDays / ;
}
}
}

工具类

//
// (C) Paul Tingey 2004
//
using System;
using System.Collections;
using System.ComponentModel; namespace OrderedPropertyGrid
{
public class PropertySorter : ExpandableObjectConverter
{
#region Methods
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
} public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
//
// This override returns a list of properties in order
//
PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);
ArrayList orderedProperties = new ArrayList();
foreach (PropertyDescriptor pd in pdc)
{
Attribute attribute = pd.Attributes[typeof(PropertyOrderAttribute)];
if (attribute != null)
{
//
// If the attribute is found, then create an pair object to hold it
//
PropertyOrderAttribute poa = (PropertyOrderAttribute)attribute;
orderedProperties.Add(new PropertyOrderPair(pd.Name,poa.Order));
}
else
{
//
// If no order attribute is specifed then given it an order of 0
//
orderedProperties.Add(new PropertyOrderPair(pd.Name,));
}
}
//
// Perform the actual order using the value PropertyOrderPair classes
// implementation of IComparable to sort
//
orderedProperties.Sort();
//
// Build a string list of the ordered names
//
ArrayList propertyNames = new ArrayList();
foreach (PropertyOrderPair pop in orderedProperties)
{
propertyNames.Add(pop.Name);
}
//
// Pass in the ordered list for the PropertyDescriptorCollection to sort by
//
return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));
}
#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 #region Helper Class - PropertyOrderPair
public class PropertyOrderPair : IComparable
{
private int _order;
private string _name;
public string Name
{
get
{
return _name;
}
} public PropertyOrderPair(string name, int order)
{
_order = order;
_name = name;
} 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 -;
}
return ;
}
}
#endregion
}

  属性排序方式

  属性的排序是基于容器类的.sort();实现的。因为控件通过TypeConverter.GetProperties();方法获得PropertyDescriptorCollection类型的对象。并根据此对象的元素设定SelectedObject的表现方式等。故实现属性类的排序首先需要获得对象的集合,然后使其按指定方式排序。因为sort()方法接受string[]类型的参数作为排序依据,其相对于属性的排序是比对其Name属性(或DisplayName属性),而我们需要在保证本地化的前提下完成排序,所以我们要在抛开其Name属性(或者DisplayName)的前提下实现排序(理论上我们能获得属性property的name属性,即方法名,但是笔者在实践中设定字符串数组中依次填入name作为排序依据,未能成功,非本地化的情况下可以实现,现在仍未找到原因,猜测其可能会以DisplayName替代Name返回???)。基于以上分析与原因,我们需要给每个属性Property添加一个属性Attribute可以作为排序的依据。到此,存在一个问题。如何根据新的属性(代称为order)对Property进行排序。较为优雅的方法是实现IComparable()接口。

  事例代码如下:(部分代码来源于网络,感谢先辈)

[AttributeUsage(AttributeTargets.Property)]
public class PropertyOrderAttribute : Attribute//自定义Attribute类,向property提供 ```````````````````````````````````````````````````//order属性
{
private int order; public PropertyOrderAttribute(int order)
{
this.order = order;
} public int Order
{
get
{
return order;
}
}
} class TestPropertyDescriptor : PropertyDescriptor,IComparable//继承PropertyDescriptor类并实现IComparable接口
{
private PropertyDescriptor basePropertyDescriptor;
private int order;
... //构造函数 public TestPropertyDescriptor(PropertyDescriptor basePropertyDescriptor): base(basePropertyDescriptor)
{
this.basePropertyDescriptor = basePropertyDescriptor;
order = GetOrder(basePropertyDescriptor.Attributes);
} //获得property的order属性 private int GetOrder(AttributeCollection ac)
{
foreach (Attribute a in ac)
{
if (a is PropertyOrderAttribute)
return ((PropertyOrderAttribute)a).Order;
}
return ; } ... #region "IComparable"
public int CompareTo(object tpd)//实现接口,使此类的对象可以依据order进行比较、排序
{
TestPropertyDescriptor other = (TestPropertyDescriptor)tpd;
if (order == other.order) return string.Compare(Name, other.Name);
else return (order > other.order) ? : -;
}
#endregion
} class ICustomTDClass1: Class1 , ICustomTypeDescriptor//Class1为需要对其属性进行排序的自定义类。 { ... public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{ PropertyDescriptorCollection tmpPDC = TypeDescriptor.GetProperties(typeof(ICustomTDClass1), attributes);
PropertyDescriptorCollection result = new PropertyDescriptorCollection(null);
ArrayList orderPdList = new ArrayList(); foreach (PropertyDescriptor pd in tmpPDC)
{
TestPropertyDescriptor tpd = new TestPropertyDescriptor(pd);
result.Add(tpd);
orderPdList.Add(tpd); }
orderPdList.Sort();//根据order排序
ArrayList propertyNames = new ArrayList();
foreach (TestPropertyDescriptor propertyAttributes in orderPdList)//获得排序后的DisplayName数组
{
propertyNames.Add(propertyAttributes.DisplayName);
} return result.Sort((string[])propertyNames.ToArray(typeof(string)));//根据数组对结果排序,注意这里不能直接return `````````````````````````````````````````````````````````````````````````````````````````````//result.Sort(),因为在result里存着的是PropertyDescriptor类`````````````````````````````````````````````````````````````````````````````````````````````//型的对象,而不是我们定义的TestPropertyDescriptor类`````````````````````````````````````````````````````````````````````````````````````````````//型。至此,排序功能圆满完成。
}
... }

参考

1. PropertyGrid排序

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

3. Ordering Items in the Property Grid

PropertyGrid—属性类别排序的更多相关文章

  1. 数据网格和树-EasyUI Datagrid 数据网格、EasyUI Propertygrid 属性网格、EasyUI Tree 树、EasyUI Treegrid 树形网格

    EasyUI Datagrid 数据网格 扩展自 $.fn.panel.defaults.通过 $.fn.datagrid.defaults 重写默认的 defaults. 数据网格(datagrid ...

  2. 对JavaScript对象数组按指定属性和排序方向进行排序

    引子 在以数据为中心的信息系统中,以表格形式展示数据是在常见不过的方式了.对数据进行排序是必不可少的功能.排序可以分为按单个字段排序和按多个字段不同排序方向排序.单字段排序局限性较大,不能满足用户对数 ...

  3. java对对象或者map的属性进行排序

    package com.xkj.spider.mpb.util; import java.lang.reflect.Method; import java.util.HashMap; import j ...

  4. java list按照 对象 指定多个字段属性进行排序

    ListUtils.Java---功能类 package PjectUtils; import java.lang.reflect.Field; import java.text.NumberForm ...

  5. java list按照元素对象的指定多个字段属性进行排序

    ListUtils.java---功能类 package com.enable.common.utils; import java.lang.reflect.Field;import java.tex ...

  6. WPF 针对数据源某个属性进行排序

    原文:WPF 针对数据源某个属性进行排序 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/wanlong360599336/article/detai ...

  7. JS 对象属性名排序

    问题,对象属性名排序,如: var data = { A:[], D:[], B:{} } 调整为=> var data = { A:[], B:[], D:{} } 方法一: for,in,把 ...

  8. array排序(按数组中对象的属性进行排序)

    使用array.sort()对数组中对象的属性进行排序 <template> <div> <a @click="sortArray()">降序& ...

  9. Django-model模型中Field属性类别及选项

    参考:[Django官方文档] Django所使用模型中一些属性类别及选项(Field and Options) 1. Models Field 各种类型分别对应数据库中的各种类型,这是Django对 ...

随机推荐

  1. Leetcode 583.两个字符串的删除操作

    两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例 1: 输入: "se ...

  2. Linux抓包工具tcpdump命令详解

    1.简介      用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中 ...

  3. 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组

    题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...

  4. bzoj1902【Zju2116】 Christopher

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1902 sol  :一眼可以看出此题应用了lucas定理(逃~ 将n,m都化为p进制,记为a[] ...

  5. 解决IIS无法访问远程映射目录

    由于影像系统(PACS)需要存储大量影像文件动辄几十T,所以经常会用到远程影像的独立文件盘, 挂载了远程映射盘后,本机可以直接访问 IIS中就直接报错了 . A机器:IIS WEB服务器 B机器:文件 ...

  6. LOJ#2131. 「NOI2015」寿司晚宴

    $n \leq 500$,$2-n$这些数字,两个人挑,可以重复挑,问有几种方案中,一个人选的所有数字与另一个人选的所有数字都互质. 不像前两题那么抠脚.. 如果$n$比较小的话,可以把两个人选的数字 ...

  7. 为IIS添加json扩展类型文件的MiME类型

    IIS6.0 1.打开IIS添加Mime项 关联扩展名:*.json内容类型(MIME):application/x-javascript      2.添加映射: 位置在IIS对应站点右键属性:”主 ...

  8. 控制台或Winform程序中如何编码或解码Server.URLEncode

    原文发布时间为:2010-07-10 -- 来源于本人的百度文章 [由搬家工具导入] 在Asp.net中可以使用Server.HTMLEncode和Server.URLEncode 将文本或URL的特 ...

  9. AJAX在VS2005中的简单应用 使用ajaxpro.2.dll[点击按钮执行事件不刷新]

    原文发布时间为:2008-10-21 -- 来源于本人的百度文章 [由搬家工具导入] 1.下載ajaxpro.dll或AjaxPro.2.dll 放在Bin文件夹中2.配置web.config 3.u ...

  10. uva 1442:Cave(贪心)

    题意:一个洞穴长n,告诉你每个位置的地面高度和顶部高度,让你往里灌水,要求水不能碰到天花板(但可以无限接近).求最多的水量.(洞穴两边视为封闭) 思路:如果知道一个位置向左看最高可以多高,向右看最高可 ...