The other day I was looking to be able to sort a list of products (List<Product>). I was binding that list to a ListView and the client wanted to be able to sort the Products by Name (Z-A & A-Z) and by Price (Low-High and High-Low).
I initially had something like this:
public class SortProductsByPrice : IComparer { public int Compare(Product Prod1, Product Prod2) { return Prod1.Price.CompareTo(Prod2.Price); } }
That works, but I didn’t want to write a class for everything I wanted to be able to sort by. For what the client wanted above I would have had to write 4 different classes.
So I set off looking for an awesome way to write one sort method. Sparing you the endless results of clicking through many search results and articles, I ran across a couple things caught my attention: .Net Reflection, hey look I can see myself! and How to sort a ListView control by a column in Visual C#.
Combining ideas from both of those examples above I produced a class that will Sort a List of any objects.
public class Sort : IComparer { // Specifies the Property to be sorted public String SortBy { get; set; } // Specifies the order in which to sort (i.e. 'Ascending'). public SortDirection OrderOfSort { get; set; } public Sort(String SortBy, SortDirection OrderOfSort) { this.SortBy = SortBy; this.OrderOfSort = OrderOfSort; } public int Compare(T x, T y) { int compareResult; Type MyTypeObject = typeof(T); PropertyInfo prop = MyTypeObject.GetProperty(SortBy); if (prop == null) { return 0; } switch (prop.PropertyType.Name) { case "String": compareResult = prop.GetValue(x, null).ToString().CompareTo( prop.GetValue(y, null).ToString()); break; case "DateTime": compareResult = Convert.ToDateTime(prop.GetValue(x, null)).CompareTo( Convert.ToDateTime(prop.GetValue(y, null))); break; case "Double": compareResult = Convert.ToDouble(prop.GetValue(x, null)).CompareTo( Convert.ToDouble(prop.GetValue(y, null))); break; default: compareResult = 0; break; } switch (OrderOfSort) { case SortDirection.Ascending: return compareResult; case SortDirection.Descending: return (-compareResult); default: return 0; } } }
Now I can utilize this awesome new class by calling it like this:
ProductList.Sort("Price", SortDirection.Ascending);
The concept here is you just pass the property you want to sort by (i.e. Price) and the direction and “Bam” (as Emeril says)!
The next step here would just be to add some additional cases to my switch statement to check for other DataTypes (like Decimal, Int, etc).