6

Let's say I have a class like this

public class model
{
    public int id{get;set;}
    public string name{get;set;}
    public string department{get;set;}
}

and I have a List of type model

List<model> modelList = List<model>();

How Can I sort the modelList by its column name with sort direction?

Ways that I tried:

public List<model> sortModelList(string columnName, SortDirection direction)
{
   //Method 1:
   //The below code was unable to sort by column and unable to set the sort direction
   return modelList.Sort();

   //Method 2:
   //The below code was unable to sort by the columnName parameter and unable to set the sort direction
   return modelList.OrderBy(a=>a.name)

  //What I can do in order to sort the list by "columnName" parameter and set the sort direction? (Ascending / Descending)
}
pravprab
  • 2,255
  • 3
  • 24
  • 40
User2012384
  • 4,382
  • 15
  • 60
  • 97
  • The simple answer is that you need a customer compare function. I'm sure that, very soon, someone will show you how. – david.pfx Mar 12 '14 at 03:27
  • 1
    look at the post at this page: http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet – Emad Mar 12 '14 at 03:31

5 Answers5

11

If you need to pass column name as a parameter, then you would need to use reflection to do your comparison. You can do something like below:

modelList.OrderBy(a => a.GetType().GetProperty(columnName).GetValue(a, null));

Of course you would have to do proper null checks etc, which I am assuming you would be able to take care of.

Charles Prakash Dasari
  • 4,539
  • 1
  • 23
  • 44
  • Thanks, this was exactly what i was looking for :) – IteratioN7T Nov 01 '18 at 11:23
  • `LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object, System.Object[])' method, and this method cannot be translated into a store expression` just so you know this completely removes the point of using iqueryable. – Niklas Sep 26 '20 at 14:26
8

I think you're looking for the overload of Sort() that takes a comparison function .

For example:

modelList.Sort((m1, m2) => string.Compare(m1.name, m2.name));
// descending
modelList.Sort((m1, m2) => -string.Compare(m1.name, m2.name));

OrderBy has similar flexibility, but returns a new sequence which is sorted rather than modifying the original list. So, you could do:

var newList = modelList.OrderBy(m => m.name).ToList();
// descending
var newList = modelList.OrderByDescending(m => m.name).ToList();

To specify the property to be sorted by dynamically, consider the following code:

public void SortList<T>(List<T> list, string columnName, SortDirection direction)
{
    var property = typeof(T).GetProperty(columnName);
    var multiplier = direction == SortDirection.Descending ? -1 : 1;
    list.Sort((t1, t2) => {
        var col1 = property.GetValue(t1);
        var col2 = property.GetValue(t2);
        return multiplier * Comparer<object>.Default.Compare(col1, col2);
    });
}
ChaseMedallion
  • 19,262
  • 13
  • 76
  • 137
  • But sometimes the list won't sort by name, i.e., sometimes may sort by id, and may sort by department, is there any way to do that using this code?? – User2012384 Mar 12 '14 at 03:36
  • Thanks! That helps a lot – User2012384 Mar 12 '14 at 03:53
  • How do I use `public void public void SortList` if i wanted to sort my `List countries` for example? `countries = SortList(countries, "columnName", SortDirection.Ascending);` gives me error cannot convert void to Collections.Generic.List. – VDWWD Oct 13 '16 at 18:57
  • @VDWWD it sounds like your list type is not `List`. You could change your type to be `List`, call `ToList()` to perform the conversion, or change SortList to take the type you are using. The last option requires that the type you are using have a sort function that takes a `Comparison` or `IComparer` – ChaseMedallion Oct 14 '16 at 22:02
1

The correct way to do this is to write a customer comparison function.

Everything you need to know is found here: http://msdn.microsoft.com/en-us/library/w56d4y5z%28v=vs.110%29.aspx

Have a go, and come back if it still won't work.

david.pfx
  • 9,271
  • 2
  • 19
  • 54
1

This is where you can create a dynamic expression from property name and sort direction

Dynamic LINQ OrderBy on IEnumerable<T>

Community
  • 1
  • 1
Emad
  • 524
  • 2
  • 6
1

Step 1: Implement IComparer interface

public class SortByName : IComparer<Customer>
{
    public int Compare(Customer x, Customer y)
    {
        return x.Name.CompareTo(y.Name);
    }
}

Step 2: Pass an instance of the class that implements IComparer interface, as an argument to the Sort() method.

SortByName sortByName = new SortByName();
listModel.Sort(sortByName);
Pradeep Kesharwani
  • 1,480
  • 1
  • 11
  • 21