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

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

为属性类添加属性:[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. pb8.0 mssqlserver 新建数据库连接问题

    将ntwdblib.DLL复制到Sybase\Shared\PowerBuilder目录下 unable to load the requested database interface,无法创建数据 ...

  2. Sina微博OAuth2框架解密

    自从sina微博oauth2出来以后, 第三方集成开发简单了很多. Oauth2不像oauth1一样需要后台httpclient请求那么麻烦, 一切都可以在前台使用ajax实现了. 很多人觉得蹊跷, ...

  3. 【转】Unity3D研究院之两种方式播放游戏视频

    http://www.xuanyusong.com/archives/1019   Unity3D中播放游戏视频的方式有两种,第一种是在游戏对象中播放,就好比在游戏世界中创建一个Plane面对象,摄像 ...

  4. NSURLSession使用模板和AFNetworking使用模板(REST风格)

    1.NSURLSession使用模板 NSURLSession是苹果ios7后提供的api,用来替换 NSURLConnection会话指的是程序和服务器的通信对象//一.简单会话不可以配合会话(ge ...

  5. Hadoop入门第五篇:Hive简介以及部署

    标签(空格分隔): Hadoop Hive hwi 1.Hive简介   之前我一直在Maxcompute上进行大数据开发,所以对数仓这块还算比较了解,在接受Hive的时候基本上没什么大的障碍.所以, ...

  6. 用canvas绘制android机器人

    直接上代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  7. HDU 4845 拯救大兵瑞恩(分层图状压BFS)

    拯救大兵瑞恩 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Sub ...

  8. qw

    // 主页 @RequestMapping(value = "/home") public ModelAndView home() { ModelAndView MV = new ...

  9. bzoj4030【HEOI2015】小L的白日梦

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4030 sol  :orz Yousiki http://www.cnblogs.com/you ...

  10. IPFS

    http://www.r9it.com/20190412/ipfs-private-net.html IPFS指令集中文版(一) https://www.jianshu.com/p/ce74b32d2 ...