Home
Manage Your Code
Snippet: Multiple Sorting of Generic Collections on any property (C#)
Title: Multiple Sorting of Generic Collections on any property Language: C#
Description: This allows you to sort a collection in a generic fashion based on any property on the object. It is an update to an earlier snippet to support Generics Views: 881
Author: Babu Reddy Date Added: 4/20/2006
Copy Code  
1using System;
2using System.Collections.Generic;
3using System.Collections;
4using System.Reflection;
5
6
7namespace Ross.Utilities {
8    /// <summary>
9    /// Class used to sort objects
10    /// </summary>
11    public class Comparer<T> : System.Collections.Generic.IComparer<T> {
12        private List<SortClass> _sortClasses;
13
14        /// <summary>
15        /// The collection of sorting classes
16        /// </summary>
17        public List<SortClass> SortClasses {
18            get { return _sortClasses; }
19        }
20
21        /// <summary>
22        /// Default Constructor
23        /// </summary>
24        public Comparer() {
25            _sortClasses = new List<SortClass>();
26        }
27
28        /// <summary>
29        /// Constructor that takes a collection of sorting classes
30        /// </summary>
31        /// <param name="SortClasses">The prebuilt collection of sort information</param>
32        public Comparer(List<SortClass> SortClasses) {
33            _sortClasses = SortClasses;
34        }
35
36        /// <summary>
37        /// Constructor that takes the information about one sort
38        /// </summary>
39        /// <param name="SortColumn">The column to sort on</param>
40        /// <param name="SortDirection">The direction to sort</param>
41        public Comparer(string SortColumn, SortDirection SortDirection) {
42            _sortClasses = new List<SortClass>();
43            _sortClasses.Add(new SortClass(SortColumn, SortDirection));
44        }
45        
46        /// <summary>
47        /// IComparer interface implementation to compare two objects
48        /// </summary>
49        /// <param name="x">Object 1</param>
50        /// <param name="y">Object 2</param>
51        /// <returns></returns>
52        public int Compare(T x, T y) {
53            if(SortClasses.Count == 0) {
54                return 0;
55            }
56            return CheckSort(0, x, y);
57        }
58
59        /// <summary>
60        /// Recursive function to do sorting
61        /// </summary>
62        /// <param name="SortLevel">The current level we are sorting at</param>
63        /// <param name="MyObject1">Object 1</param>
64        /// <param name="MyObject2">Object 2</param>
65        /// <returns></returns>
66        private int CheckSort(int SortLevel, T MyObject1, T MyObject2) {
67            int returnVal = 0;
68            
69            if(SortClasses.Count - 1 >= SortLevel) {
70                object valueOf1 = MyObject1.GetType().GetProperty(SortClasses[SortLevel].SortColumn).GetValue(MyObject1, null);
71                object valueOf2 = MyObject2.GetType().GetProperty(SortClasses[SortLevel].SortColumn).GetValue(MyObject2, null);
72
73                if(SortClasses[SortLevel].SortDirection == SortDirection.Ascending) {
74                    returnVal = ((IComparable) valueOf1).CompareTo(valueOf2);
75                } 
76                else {
77                    returnVal = ((IComparable) valueOf2).CompareTo(valueOf1);
78                }
79
80                if(returnVal == 0){
81                    returnVal = CheckSort(SortLevel + 1, MyObject1, MyObject2);
82                }
83            }
84            return returnVal;
85        }
86    }
87
88    /// <summary>
89    /// Enumeration to determine sorting direction
90    /// </summary>
91    public enum SortDirection {
92        /// <summary>Sort Ascending</summary>
93        Ascending = 1,
94
95        /// <summary>Sort Descending</summary>
96        Descending = 2
97    }
98
99    /// <summary>
100    /// Class used to hold sort information
101    /// </summary>
102    public class SortClass {
103        /// <summary>
104        /// Default constructor taking a column and a direction
105        /// </summary>
106        /// <param name="SortColumn">The column to sort on</param>
107        /// <param name="SortDirection">The direction to sort.</param>
108        public SortClass(string SortColumn, SortDirection SortDirection) {
109            this.SortColumn = SortColumn;
110            this.SortDirection = SortDirection;
111        }
112
113        private string    _sortColumn;
114        
115        /// <summary>
116        /// The column to sort on
117        /// </summary>
118        public string SortColumn {
119            get { return _sortColumn; }
120            set { _sortColumn = value; }
121        }
122        
123        private SortDirection _sortDirection;
124
125        /// <summary>
126        /// The direction to sort
127        /// </summary>
128        public SortDirection SortDirection {
129            get { return _sortDirection; }
130            set { _sortDirection = value; }
131        }
132    }
133}
Usage
Comparer comparer = new Comparer();

comparer.SortClasses.Add(new SortClass("MyProperty1", SortDirection.Ascending));
comparer.SortClasses.Add(new SortClass("MyProperty2", SortDirection.Descending));

myGenericCollection.Sort(comparer);
Notes
The usage snippet will sort by MyProperty1 asc, and then by MyProperty2 desc.