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: 3066
Author: Joel Ross Date Added: 4/12/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.