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
}

url:http://greatverve.cnblogs.com/archive/2012/02/08/propergrid-order.html

參考:http://www.codeproject.com/KB/cs/orderedpropertygrid.aspx
參考:

屬性排序方式

屬性的排序是基於容器類的.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(){})。再次感謝先輩們。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM