博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PropertyGrid排序
阅读量:6618 次
发布时间:2019-06-25

本文共 6653 字,大约阅读时间需要 22 分钟。

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

为属性类添加属性:[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
}

url:

参考:

参考:

属性排序方式

属性的排序是基于容器类的.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类`````````````````````````````````````````````````````````````````````````````````````````````//型。至此,排序功能圆满完成。

        }
...

}

 

PS:并不是所有待排序的类都要重写ICustomTypeDescriptor,更加简洁的方法是自定义TypyConverter类,并在其中的GetProperties(........){}中实现(不是GetProperties(){})。再次感谢先辈们。

转载于:https://www.cnblogs.com/greatverve/archive/2012/02/08/propergrid-order.html

你可能感兴趣的文章
【总结整理】已读功能---摘自《馒头商学院》
查看>>
非抢占式系统优点
查看>>
TPYBoard V102:能跑Python的stm32开发板
查看>>
在阿里云域名https配置(nginx为例)
查看>>
TP5.0中的小知识总结
查看>>
【SSH网上商城项目实战27】域名空间的申请和项目的部署及发布
查看>>
RabbitMQ-从基础到实战(2)— 防止消息丢失
查看>>
5.1、Android Studio用Logcat编写和查看日志
查看>>
【译】ExtJS 4.1会带来什么
查看>>
正则表达式基础知识
查看>>
【ShaderToy】开篇
查看>>
wp7 城市天气预报查询
查看>>
重要的话
查看>>
银联参数
查看>>
QRegExp正则表达式用法
查看>>
a 标签的伪类的正确顺序,以及原因
查看>>
PHP中ts和nts版本 - vc6和vc9编译版本的区别
查看>>
iphone 地图:
查看>>
ES6学习总结之 Promise对象
查看>>
修改图片,保存并替换原图片时,“GDI+ 中发生一般性错误”
查看>>