PropertyGrid—属性类别排序

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

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

为属性类添加属性:[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(1975,1,1);

    [Category(PERSONAL_CAT), PropertyOrder(10)]
    public string Name
    {
        get {return _name;}
        set {_name = value;}
    }

    [Category(PERSONAL_CAT), PropertyOrder(11)]
    public DateTime Birthday
    {
        get {return _birthday;}
        set {_birthday = value;}
    }

    [Category(PERSONAL_CAT), PropertyOrder(12)]
    public int Age
    {
        get
        {
            TimeSpan age = DateTime.Now - _birthday;
            return (int)age.TotalDays / 365;
        }
    }
}

工具类

//
// (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,0));
                }
            }
            //
            // 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 -1;
            }
            return 1;
        }
    }
    #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 0;

        }

        ...

        #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) ? 1 : -1;
        }
        #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

原文地址:https://www.cnblogs.com/code1992/p/10197534.html

时间: 2024-08-30 12:00:41

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

ArcGIS10.1 属性值排序,图斑排序

ArcGIS10.1技术交流(第4期) 属性值排序,图斑排序 第一讲 介绍了arcgis10.1中的排序这一个工具,介绍了如何利用这一个工具对属性值进行排序,以及对图斑块进行一个空间排序,以及途中还介绍了一下目前网上一种比较普通方法来进行图斑排序的一个原理,再次粗略的引了一下皮亚诺曲线 点击学习 第二讲 为上一讲讲到的ArcGIs自带的排序工具的下承接(),介绍从提取图斑外接矩形的左上点坐标,导出至Excel,对得到的坐标值进行两个排序,得到一个排序值,但是重点呢,不是结果,而是告诉大家这种方法

数组内的对象按照2个属性进行排序

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> 数组内的对象按照2个属性进行排序(先按time从大到小排序,再按weight从大到小排序),请查看控制台看输出结果:<br/> var array = [<br/>

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

引子 在以数据为中心的信息系统中,以表格形式展示数据是在常见不过的方式了.对数据进行排序是必不可少的功能.排序可以分为按单个字段排序和按多个字段不同排序方向排序.单字段排序局限性较大,不能满足用户对数据的关注点变化的需求,而多字段排序就可以较好的弥补这个缺陷. 多字段排序,实现的方式从大的层面上可以分为后端实现和前端实现. 后端排序 后端实现排序可以在数据库层面实现或者在应用程序层面实现. 数据库层面实现多字段排序非常简单,使用SQL的排序指令“Order By”即可——Order By fie

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

ListUtils.Java---功能类 http://blog.csdn.net/jiangyu1013/article/details/53894218 [java] view plain copy package com.enable.common.utils; import java.lang.reflect.Field; import java.text.NumberFormat; import java.util.Collections; import java.util.Compa

java按照集合中元素的属性进行排序示例代码

public class Student { private String name; private int age; private int id; public Student() {  super(); } public Student(String name, int age, int id) {  super();  this.name = name;  this.age = age;  this.id = id; } public String getName() {  retur

java集合中对象某属性比较排序Comparable与Comparator

要对集合中的对象的某属性进行排序有两种方式. a. 一种是要排序对象类实现comparable接口的compareTo方法:然后把对象放入list:然后调用Collections.sort(list);b. 一种是不对要排序对象类做任何改动,创建Comparator接口的实现类C:然后 把对象放入list:然后调用Collections.sort(list, C); a.eg ---------------------------------- 1 public class User imple

CSS中连接属性的排序

在CSS超链接的属性中,有四个连接方式: a:link  a:hover a:visited a:acticve 之前在使用的时候一直是按照自认为的顺序中去写的,就是 L H V A的排序方式,然而有些时候却发现并不起作用了,查找了一些资料,也上网查找了一下,也有很多人在问及这个问题,如果是按照这种顺序排序,有时候显示正确,而有时候却显示不正确,追究原因,这个可能是由于浏览器的识别先后问题所导致的,也额能有缓存的原因在里面个人觉得,而最正确的写法应该是 L V H ,举个例子: <!DOCTYP

实现java.util.Comparator接口,对对象集合进行多属性组合排序

Commons - BeanUtils 提供了很多功能,其中一个很有用的是对对象集合进行排序,如Collections.sort(peoples, new BeanComparator("age")); 另外,可以使用java.util.Collections的sort方法可以对collection集合进行排序,包括多列组合排序,下面是自己实现java.util.Comparator,定制对象属性排序规则的例子: package com.lph.test; import java.ut

sort方法实际应用详解---javascript中对一个对象数组按照对象某个属性进行排序

转载: 查看原文 在javascript中,对象和数组是两种不同的类型,这和php中的数组概念不同.在javascript中,也有一些精妙的算法,用来对一些对象进行排序.我在面试迅雷的时候,也拿到一道题,当时做题的时候考虑到时间,没有去仔细研究,回来后再读了一些方法,就知道真正的考点在哪里了. 我们现在有一组"学生"对象,包含"名字,年龄"等属性,现在要求一个算法,把这些对象放在一个数组里,可以实现按照年龄对这些对象进行排序. var sdts = [ { name