none
Sorting CategoryAttributes for PropertyGrids

    Question

  • This is my first post, and I just want to say that I am so excited that I found this dev forum.  It will come in very handy for development.  Thanks everyone for being a part of it.

    I wanted to talk about Sorting Categories in property grids.  I have failed to find anything that tells me how to do it.  I have made a properties sorting class, but not category.  I have come across a way to do it.  Pardon my stupidity if everyone already knows this, but for the new devs, it will help.
     
    Lets take my example:

    This is property grid data to be shown in a windows form property grid.
    I'm not going to go into the winform code but you would set your values in the form1_load method (standard name) in your Form1.cs file.


    private void Form1_Load(object sender, System.EventArgs e)
    {
      PropertyGridData data = new PropertyGridData();  
      data.Type1 = "First Type1";
      data.Type2 = "First Type2";
      data.Type3 = "First Type3";
      
      propertyGrid1.SelectedObject = data; 
    }

     



    [DefaultPropertyAttribute("Name")]
    public class PropertyGridData
    {
      private      string     _a;
      private      string     _b;
      private      string     _c;


      [CategoryAttribute("A"), DescriptionAttribute("Type1")]
      public  string  Type1
      {
          get
         {
             return _a;
          }

          set
          {
              _a = value;
           }
       }

      [CategoryAttribute("B"), DescriptionAttribute("Type2")]
      public  string  Type2
      {
          get
          {
              return _b;
          }

          set
          {
             _b = value;
          }
       }

      [CategoryAttribute("C"), DescriptionAttribute("Type3")]
      public  int  Type3
      {
           get
           {
              return _c;
            }

           set
          {
              _c = value;
          }
      }
       public PropertyGridData()
       {
         //
         // TODO: Add constructor logic here
         //
       }
    }


     



    Now when the property grid is shown after compiling and executing, it will automatically alphabetically arrange the Category names. 
    The only way I have been able to find out to do a custom arrange is using meta characters in the attribute.

    example:

    If I want C Category to be shown first in the grid I would use the \r meta character.


    [CategoryAttribute("\r\r\rC"), DescriptionAttribute("Type3")]
     


    The more \r characters in the string, the higher up in the heiarchy it will be. 


    [CategoryAttribute("\r\rC"), DescriptionAttribute("Type3")]
    [CategoryAttribute("\rB"), DescriptionAttribute("Type2")]
    [CategoryAttribute("A"), DescriptionAttribute("Type1")]

     


    This will give you C, B, then A Categories.

    I hope this helps some of you guys that have been looking for information on category propertygrid sorting.

    Cheers
    - Sipes

    Friday, May 13, 2005 9:24 PM

Answers

  • Ahhh you want to sort the properties within the categories??? muahahahhaha I wrote a class for that:



    implement it like this:

    Add [TypeConverter(typeof(PropertySorter))] before your class wherever your data is.... and then this is how you call PropertyOrder:


    [CategoryAttribute("\r\r\rIdentity"), DescriptionAttribute("Class"), PropertyOrder(2)]

    [CategoryAttribute("\r\r\rIdentity"), DescriptionAttribute("Type"), PropertyOrder(1) ]


     



    When you add it as a parameter within your [ ] brackets, call "PropertyOrder" with the lowest number being the first in the list of properties in the category.

    It will show up like this

    Identity
    1. Type
    2. Class

    in that order.

    PropertyOrder code :


    using System;
    using
    System.Collections;
    using
    System.ComponentModel;

    namespace PropertySorter
    {
        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
    }


     



    Enjoy!

    Friday, June 03, 2005 2:43 PM

All replies

  • As I'm a new to C# I can say 'This is nice! This I can use.' Big Smile

    Only....
    I've tried

    [CategoryAttribute("\rSetting"), DescriptionAttribute("bladibla")]
     

    It shows me a <blank> category instead of the 'Setting' I'm expecting.
    I'm working with VS2005 (beta2).

    And, related to sorting the category's, is there a way to sort the elements within a category?

    Tuesday, May 17, 2005 9:48 AM
  • Ahhh you want to sort the properties within the categories??? muahahahhaha I wrote a class for that:



    implement it like this:

    Add [TypeConverter(typeof(PropertySorter))] before your class wherever your data is.... and then this is how you call PropertyOrder:


    [CategoryAttribute("\r\r\rIdentity"), DescriptionAttribute("Class"), PropertyOrder(2)]

    [CategoryAttribute("\r\r\rIdentity"), DescriptionAttribute("Type"), PropertyOrder(1) ]


     



    When you add it as a parameter within your [ ] brackets, call "PropertyOrder" with the lowest number being the first in the list of properties in the category.

    It will show up like this

    Identity
    1. Type
    2. Class

    in that order.

    PropertyOrder code :


    using System;
    using
    System.Collections;
    using
    System.ComponentModel;

    namespace PropertySorter
    {
        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
    }


     



    Enjoy!

    Friday, June 03, 2005 2:43 PM
  • I am trying to sort the categories in a property grid as you described. Previously I used \t, but this now displays a square symbol for an unprintable character followed by the text. I found this post and tried \r, however I then get no text at all.

    Does \r work for anyone else? June CTP of framework,.

    Thanks
    Wednesday, June 22, 2005 10:46 PM
  • Works with the example I gave.  Read it.
    Monday, June 27, 2005 9:35 PM
  • I am only interested in sorting the categories, not the properties in a category. You suggest using \r, but as Coretta also mentioned, this does not work. Do you have it working on a recent build, e.g. June CTP.

    Thursday, July 14, 2005 11:33 AM
  • I'm using the VSNET with the follow info:

    Microsoft Development Environment 2003 Version7 1 3088
    Microsoft.NET Framework 1.1 Version1 1 4322 SP1
    Copyright 1998 2002 Microsoft Corporation. All rights reserved

    The "\r" works like a charm! 10x for the tip!Smile
    Friday, July 22, 2005 9:24 PM
  • Well \t worked fine as well in VS 2003, but neither work in VS2005, since about the April CTP. Anyone got a VS2005 solution?
    Friday, July 22, 2005 9:30 PM
  • Taking up again this question: someone has resolved how to sort the categories in VSNET 2005?. The \r does not works in this release of VSNET2005 (FINAL). I need sort the categories in my project. I want to say that this tip works fine in VSNET 2003.

    Regards
    Wednesday, November 02, 2005 3:40 PM
  • Has anyone found a way to do this in VS2005? The \t and \r solutions both work in VS2003 but they don't in 2005.
    Wednesday, January 04, 2006 3:21 PM
  • I have ran into the same problem in VS2005, does anyone know of a solutions????
    Thursday, March 02, 2006 4:36 PM
  • This is so cool.

    Now I can do both Sorting CategoryAttributes by Matt's code and sorting categories by using '\t'

    Thursday, April 06, 2006 10:09 PM
  • Has anybody come up with a way to do this with VS2005 yet?

    I've been asked to sort categories in a property grid, and this is the only topic I could find anywhere that discusses it.

    Wednesday, May 03, 2006 8:07 PM
  • \t or \r may work for you, but does not work for everyone. The logic is sound, but some combination of settings means that these characters are sometimes hidden, and sometimes displayed as non-printable characters, the small square.

    I opened a PSS case, and the response was if it works it works, otherwise there is no better way of doing this as the sorting for the grid is hardcoded, so no way to override or influence it. In my case I always see the square.

    Wednesday, May 03, 2006 8:58 PM
  • I've submitted a feature request (Suggestion) to Microsoft for a way of doing this.

    If it's important to you, go to http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=4d30a974-7bfe-4f8d-af5e-39b27306d726 and vote on this feature so it gets some attention.

    Thursday, May 04, 2006 2:13 PM
  • can someone help me to translate these codes into c++?
    Wednesday, December 13, 2006 7:43 AM
  • I have problems converting the code into c++. Can anyone help me out? Thanks.
    Tuesday, December 19, 2006 3:07 AM
  • If you look at the code for System.Windows.Forms.PropertyGridInternal.SingleSelectRootGridEntry.CategorizePropEntries() using Reflector in .NET 2.0, you will see that it sorts the categories using System.Windows.Forms.StringSorter.Sort() near the end of the method.  The single call to StringSorter.Sort() is where the categories get alphabetized.  As far as I can tell, there is no way to overcome this behavior given the implementation.
    Thursday, March 22, 2007 9:52 PM
  • Hi all

     

    Saddly this does not help me sort the categories but i though ya mght want a C++ version of the CS posted code

     

    If anyone knows how to sort categories that does not sue the NOW DEFUNCED \t\t\t or \ar\r\r\r\r hack can ya post it im cong insae with these dam stupid \t black rectangles :¬(

     

    C++ CLI code below

     

    #pragma once

    namespace xxxxxxxx

    {

    using namespace System;

    using namespace System::Collections;

    using namespace System::ComponentModel;

    // Helper Class - PropertyOrderAttribute

    [AttributeUsage(AttributeTargets:Stick out tongueroperty)]

    public ref class PropertyOrderAttribute : public Attribute

    {

    // Simple attribute to allow the order of a property to be specified

    private: int _order;

    public: PropertyOrderAttribute(int order)

    {

    _order = order;

    }

    public: property int Order{

    int get(){return _order;}

    }

    };

    // Helper Class - PropertyOrderPair

    public ref class PropertyOrderPair : public IComparable

    {

    private: int _order;

    private: String ^_name;

    public: PropertyOrderPair(String ^name, int order)

    {

    _order = order;

    _name = name;

    }

    public: property String ^Name{

    String ^get(){return _name;}

    }

    public: virtual 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 order not specified, sort by name

    if(otherOrder == _order){

    String ^otherName = ((PropertyOrderPair ^)obj)->_name;

    return String::Compare(_name,otherName);

    }else if(otherOrder > _order){

    return -1;

    }

    return 1;

    }

    };

    public ref class PropertySorter : public ExpandableObjectConverter

    {

    // Methods

    public: virtual bool GetPropertiesSupported(ITypeDescriptorContext ^context) override

    {

    return true;

    }

    public: virtual PropertyDescriptorCollection ^GetProperties(ITypeDescriptorContext ^context, Object ^value, array<Attribute^> ^attributes) override

    {

    // This override returns a list of properties in order

    PropertyDescriptorCollection ^pdc = TypeDescriptor::GetProperties(value, attributes);

    ArrayList ^orderedProperties = gcnew ArrayList();

    for each(PropertyDescriptor ^pd in pdc){

    Attribute ^attribute = pd->Attributes[PropertyOrderAttribute::typeid];

    // If the attribute is found, then create an pair object to hold it

    if(attribute != nullptr){

    PropertyOrderAttribute ^poa = (PropertyOrderAttribute ^)attribute;

    orderedProperties->Add(gcnew PropertyOrderPair(pd->Name,poa->Order));

    // If no order attribute is specifed then given it an order of 0

    }else{

    orderedProperties->Add(gcnew 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

    // YES I cant be bothered

    int i=0;

    for each(PropertyOrderPair ^pop in orderedProperties){

    i=i+1;

    }

    array<String ^> ^propertyNames = gcnew array<String ^>(i);

    i=0;

    for each(PropertyOrderPair ^pop in orderedProperties){

    propertyNamesIdea=pop->Name;

    i=i+1;

    }

    // Pass in the ordered list for the PropertyDescriptorCollection to sort by

    return pdc->Sort(propertyNames);

    }

    };

    }

     

    Tuesday, June 05, 2007 4:37 PM
  • Some people mentioned that using \t \r no longer works now (VS2005 sp1) etc

     

    I found this too so i searched for why eventualy I finaly found the sausage

     

    in the main application (c++) in my case i had to toggle a default to get rid of the square blocks

     

    //Application:Tongue TiedetCompatibleTextRenderingDefault(false);

    Application:Tongue TiedetCompatibleTextRenderingDefault(true); // Ignore non printable characters in categoryies

    // God knows what else :¬(

     

     

    Tuesday, June 05, 2007 5:55 PM
  • Here is the C++ conversion of the supplied CS code to do the property sorting

     

    #pragma once

    // Add [TypeConverter(PropertySorter::typeid)] before any class that needs it and

    // [PropertyOrder(xxxx)] after category lowest numbers show 1st and if not use 0 is assumed

    // Could use to make Xmin show up before Xmax etc

    namespace PropertySorter

    {

    using namespace System;

    using namespace System::Collections;

    using namespace System::ComponentModel;

    // Helper Class - PropertyOrderAttribute

    [AttributeUsage(AttributeTargets:Stick out tongueroperty)]

    public ref class PropertyOrderAttribute : public Attribute

    {

    // Simple attribute to allow the order of a property to be specified

    private: int _order;

    public: PropertyOrderAttribute(int order)

    {

    _order = order;

    }

    public: property int Order{

    int get(){return _order;}

    }

    };

    // Helper Class - PropertyOrderPair

    public ref class PropertyOrderPair : public IComparable

    {

    private: int _order;

    private: String ^_name;

    public: PropertyOrderPair(String ^name, int order)

    {

    _order = order;

    _name = name;

    }

    public: property String ^Name{

    String ^get(){return _name;}

    }

    public: virtual 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 order not specified, sort by name

    if(otherOrder == _order){

    String ^otherName = ((PropertyOrderPair ^)obj)->_name;

    return String::Compare(_name,otherName);

    }else if(otherOrder > _order){

    return -1;

    }

    return 1;

    }

    };

    public ref class PropertySorter : public ExpandableObjectConverter

    {

    // Methods

    public: virtual bool GetPropertiesSupported(ITypeDescriptorContext ^context) override

    {

    return true;

    }

    public: virtual PropertyDescriptorCollection ^GetProperties(ITypeDescriptorContext ^context, Object ^value, array<Attribute^> ^attributes) override

    {

    // This override returns a list of properties in order

    PropertyDescriptorCollection ^pdc = TypeDescriptor::GetProperties(value, attributes);

    ArrayList ^orderedProperties = gcnew ArrayList();

    for each(PropertyDescriptor ^pd in pdc){

    Attribute ^attribute = pd->Attributes[PropertyOrderAttribute::typeid];

    // If the attribute is found, then create an pair object to hold it

    if(attribute != nullptr){

    PropertyOrderAttribute ^poa = (PropertyOrderAttribute ^)attribute;

    orderedProperties->Add(gcnew PropertyOrderPair(pd->Name,poa->Order));

    // If no order attribute is specifed then given it an order of 0

    }else{

    orderedProperties->Add(gcnew 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

    int i=0;

    for each(PropertyOrderPair ^pop in orderedProperties){

    i=i+1;

    }

    array<String ^> ^propertyNames = gcnew array<String ^>(i);

    i=0;

    for each(PropertyOrderPair ^pop in orderedProperties){

    propertyNamesIdea=pop->Name;

    i=i+1;

    }

    // Pass in the ordered list for the PropertyDescriptorCollection to sort by

    return pdc->Sort(propertyNames);

    }

    };

    }

     

     

    Tuesday, June 05, 2007 5:58 PM
  • Sorry for the smiley i have no idea how they appear i said "this post contains code" so i expected it not to mess with it but ....
    Tuesday, June 05, 2007 6:00 PM
  • \r character works in VS2005 professional edition. Try this again for sorting. I just tried and successful.
    Tuesday, July 24, 2007 1:11 PM
  • Have a read of some more posts, been there, tried it, and it will only work sometimes.
    Tuesday, July 24, 2007 8:03 PM
  • I posted a workaround for this problem. To make your life a little easier I will paste this workaround below this line.

     

    This workaround uses the same idea as the \r and \t character insertion method, mentioned in the forum topic. The problem with this method in VS2005 was that this would render an extra character or nothing at all. To correct this I am not using a \r or \t character, but a \u200B Unicode character know as the zero width space. This character is not supported by all fonts, so you also need to change the font of the property grid to something like Arial Unicode MS or Lucida Sans Unicode. Just like the \r and \t method you can add more \u200B characters to push the category further up.

     

    I hope this helps.

    Saturday, August 04, 2007 12:59 PM
  • Just in case someone is still looking for a temporary solution for this.

     

    In VB.NET 2005 I am using a combination of Chr(31) & Chr(32) pairs to create the sort of categories. The nice thing is that the Chr(31) makes the Chr(32) (space) disappear from the displayed text. Hope this helps someone...

     

    I.E.

    Const SortChar As String = Chr(31) & Chr(32)

     

    CategoryAttribute("A")

    CategoryAttribute(SortChar & "B")

     

    This will cause category "B" to display first in the property grid.

    Wednesday, March 26, 2008 5:34 AM
  • Thanks cgriitton. Your solution works.
    Not only Chr(32)(space), but also any alphabet or number. Order by the char behind chr(31).
    Saturday, March 28, 2009 4:53 AM
  • As I'm a new to C# I can say 'This is nice! This I can use.' Big Smile

    Only....
    I've tried

    [ CategoryAttribute ( "\rSetting" ), DescriptionAttribute("bladibla")]
     

    It shows me a <blank> category instead of the 'Setting' I'm expecting.
    I'm working with VS2005 (beta2).

    And, related to sorting the category's, is there a way to sort the elements within a category?


    Same issue using VS2008 with SP1. I can't believe that MS does not implement a mechanism to do this task. The attributes Order and ShowOnlyCustomProps must to be available.
    • Proposed as answer by Tabas Wednesday, April 01, 2009 6:27 PM
    Wednesday, April 01, 2009 4:36 PM
  • /*This code works for me in VS2008. Thank you a lot.

    This sample uses a Label control with customized properties. Three properties are added and sorted into a category
    Implementing some changes.. you can "filter" the not customized categories:

    Create a User Control
    Place a Label control
    Place a ImageList control and added four images: chat, error, info, lock

    */


    See image :

    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections;


    namespace STLabel
    {
        /*Modified by: César F. Qüeb Montejo */

        [TypeConverter(typeof(PropertySorter.PropertySorter))]
        public partial class STLabel : UserControl
        {
                
            public enum EImagenPredeterminada
            {
                Chat,
                Error,
                Info,
                Protegido
            }
           
            private Image _Imagen;
            private ContentAlignment _PosImage;
            private EImagenPredeterminada _TipoImagen;
            private string _Texto;
            public STLabel()
            {
                InitializeComponent();
            }

            [Description("La imagen a mostrar en la etiqueta o liga")]
            [Category("Smartechnology")]
            [Browsable(true)]
            [DisplayName("Imagen a Mostrar")]
            [PropertySorter.PropertyOrder(2)]
            public Image ImagenPersonalizada
            {
                get
                {
                    return _Imagen;
                }
                set
                {
                    if (_Imagen == value)
                        return;
                    _Imagen = value;
                    STLbl.Image = _Imagen;
                   
                }
            }

            [Description("La posición de la imagen a mostrar en la etiqueta o liga")]
            [Category("Smartechnology")]
            [Browsable(true)]
            [DisplayName("Posición")]
            [PropertySorter.PropertyOrder(3)]
            public ContentAlignment PosImage
            {
                get
                {
                    return _PosImage;
                }
                set
                {
                    if (_PosImage == value)
                        return;
                    _PosImage = value;
                    STLbl.ImageAlign= _PosImage;
                }
            }

            [Description("Imagen predeterminada")]
            [Category("Smartechnology")]
            [Browsable(true)]
            [DisplayName("Tipo de imagen predefinida")]
            [PropertySorter.PropertyOrder(1)]
            public EImagenPredeterminada TipoImagen
            {
                get
                {
                    return _TipoImagen;
                }
                set
                {
                    if (_TipoImagen == value)
                        return;
                    _TipoImagen = value;
                    switch ((int)_TipoImagen)
                    {
                        case 0:
                            ImagenPersonalizada = imageList1.Images["Chat"];
                            break;
                        case 1:
                            ImagenPersonalizada = imageList1.Images["Error"];
                            break;
                        case 2:
                            ImagenPersonalizada = imageList1.Images["Info"];
                            break;
                        case 3:
                            ImagenPersonalizada = imageList1.Images["Lock"];
                            break;

                    }
                }
            }

            [Description("El texto a mostrar en la etiqueta")]
            [Category("Smartechnology")]
            [Browsable(true)]
            [DisplayName("Texto a mostrar")]
            [PropertySorter.PropertyOrder(4)]
            public string Texto
            {
                get
                {
                    return _Texto;
                }
                set
                {
                    if (_Texto == value)
                        return;
                    _Texto = value;
                    STLbl.Text = _Texto;
                }
            }
        }
    }

    namespace PropertySorter
    {
        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);
                PropertyDescriptor[] properties = new PropertyDescriptor[] { };
                ArrayList orderedProperties = new ArrayList();

                /* property at below used to copy ONLY properties in an specific category */
                PropertyDescriptorCollection props = new PropertyDescriptorCollection(properties);
                foreach (PropertyDescriptor pd in pdc)
                {
                    // used to filter for category
                    if (pd.Category == "Smartechnology")
                    {
                        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;

                            /* You can pass ONLY the PropertyDescriptor.. but..you know.. i'm testing..*/
                            /* This line was adapted from original code */
                            orderedProperties.Add(new PropertyOrderPair(pd.Name, poa.Order, pd.Category, pd));


                        }
                        else
                        {
                            //
                            // If no order attribute is specifed then given it an order of 0
                            //

                             /* You can pass ONLY the PropertyDescriptor.. but..you know.. i'm testing..*/
                            /* This line was adapted from original code */
                            orderedProperties.Add(new PropertyOrderPair(pd.Name, 0, pd.Category, pd));
                        }
                    }
                }
               
                //
                // 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)
                {
                    /* !!!! The FILTER is implemented here !!!! */
                    /* TYPE your OWN category */
                     if (pop.Category.ToLower() == "smartechnology")
                    {
                        propertyNames.Add(pop.Name);
                        props.Add(pop.PropDescriptor);
                    }
                  

                }
                //
                // Pass in the ordered list for the PropertyDescriptorCollection to sort by
                //
                /* We are returning the personalized properties only */
                return props.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;
            /* Following two members added by CFQüeb */
            private string _category;
            private PropertyDescriptor _propDescriptor;
            public string Name
            {
                get
                {
                    return _name;
                }
            }
             /* Following property added since original code */
            public string Category
            {
                get
                {
                    return _category;
                }
                set
                {
                    if (_category == value)
                        return;
                    _category = value;
                }
            }
            /* Following property added since original code */
            public PropertyDescriptor PropDescriptor
            {
                get
                {
                    return _propDescriptor;
                }
                set
                {
                    if (_propDescriptor == value)
                        return;
                    _propDescriptor = value;
                }
            }
           
             /* Modified constructor */
            public PropertyOrderPair(string name, int order, string category, PropertyDescriptor propdesc)
            {
                _order = order;
                _name = name;

                /* next two members were added by CFQüeb */
                _category = category;
                _propDescriptor = propdesc;
            }

            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
    }

    /* Using this code... you get the properties sorted and all other categories from class base (inherited) discarted

    Enjoy!!!!
    César F. Qüeb Montejo */
    • Proposed as answer by Tabas Wednesday, April 01, 2009 7:17 PM
    Wednesday, April 01, 2009 6:42 PM