0

I had a typed DataTable which to sort was just something like:

DataTable.DefaultView.Sort("sortexpression");

Because the sort expression was a string I could just append both the sort field and direction in a couple of lines, regardless of how many sort options I had. Now with Linq Im clearly doing something very wrong because to do something similar I'm doing this:

             this.GetSortExpressions();
        if ((ViewState["SortDirection"] as string) == "ASC")
        {
            switch (ViewState["SortField"] as string)
            {
                case "LKey":
                    this.SortedDetails = this.Details.OrderBy(d => d.LKey);
                    break;
                case "MName":
                    this.SortedDetails = this.Details.OrderBy(d => d.MaterialName);
                    break;
                case "FMSQOH":
                    this.SortedDetails = this.Details.OrderBy(d => d.FMSQOH);
                    break;
                case "CCQOH":
                    this.SortedDetails = this.Details.OrderBy(d => d.CCQOH);
                    break;
                case "FMSQOHVary":
                    this.SortedDetails = this.Details.OrderBy(d => d.FMSQOHVary);
                    break;
                default:
                    this.SortedDetails = this.Details.OrderBy(d => d.LKey);
                    break;
            }
        }
        else
        {
            switch (ViewState["SortField"] as string)
            {
                case "LKey":
                    this.SortedDetails = this.Details.OrderByDescending(d => d.LKey);
                    break;
                case "MName":
                    this.SortedDetails = this.Details.OrderByDescending(d => d.MaterialName);
                    break;
                case "FMSQOH":
                    this.SortedDetails = this.Details.OrderByDescending(d => d.FMSQOH);
                    break;
                case "CCQOH":
                    this.SortedDetails = this.Details.OrderByDescending(d => d.CCQOH);
                    break;
                case "FMSQOHVary":
                    this.SortedDetails = this.Details.OrderByDescending(d => d.FMSQOHVary);
                    break;
                default:
                    this.SortedDetails = this.Details.OrderByDescending(d => d.LKey);
                    break;
            }
        }

It's god awful. I'm concerned about the fact that Im adding 2*n case statements for every new sort field. What is the right way please?

rism
  • 11,221
  • 14
  • 70
  • 110
  • Why are you casting the result of `OrderByDescending` to a `IOrderedEnumerable`? It already returns that. – M.Babcock Mar 08 '12 at 04:54
  • Hi, I've just cleaned that up. It was hangover from a previous muddle. – rism Mar 08 '12 at 04:59
  • Do you have control over ``ViewState["SortField"]`` and it's type? If so, can you make it something else then ``string``? The whole point of LINQ is to have type safety - strings take that away from you. – Jacek Gorgoń Mar 08 '12 at 08:15
  • How about htis one: http://stackoverflow.com/questions/41244/dynamic-linq-orderby – Gert Arnold Mar 08 '12 at 09:15

2 Answers2

1

I have been gone through this.. what i found lastly was a generic solution that use reflection to sort a IEnumerable object.

http://zhousanfeng.wordpress.com/2009/12/01/a-generic-comparersorter-class%E8%BD%AC/

this will be how you could use it

Sorter<TestClass> sort = new Sorter<TestClass>(this.Deatils, "LKey ASC");
List<TestClass> sorted = sort.GetSortedList();

Regards.

Shoaib Shaikh
  • 4,480
  • 1
  • 23
  • 35
0

Assign a Func to the orderby method before performing the sort (untested):

public IOrderedEnumerable<TSource> OrderFunc<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector
);
OrderFunc order;
if ((ViewState["SortDirection"] as string) == "ASC")
    order = Enumerable.OrderBy;
else
    order = Enumerable.OrderByDescending;

switch (ViewState["SortField"] as string)
{
    case "LKey":
        this.SortedDetails = order(this.Details, d => d.LKey);
    break;
    case "MName":
        this.SortedDetails = order(this.Details, d => d.MaterialName);
    break;
    case "FMSQOH":
        this.SortedDetails = order(this.Details, d => d.FMSQOH);
    break;
    case "CCQOH":
        this.SortedDetails = order(this.Details, d => d.CCQOH);
    break;
    case "FMSQOHVary":
        this.SortedDetails = order(this.Details, d => d.FMSQOHVary);
    break;
    default:
        this.SortedDetails = order(this.Details, d => dLKey);
    break;
}
M.Babcock
  • 18,075
  • 5
  • 50
  • 83
  • Thx, Looks like a great start knocking over the sort direction. Any way to also condense the sort field determination? – rism Mar 08 '12 at 05:06
  • If you could make all of the values of `ViewState["SortField"]` the name of the property then would could probably do it with Reflection. If not then it'd be slightly more difficult but it should be doable with a constant array to perform the mapping. – M.Babcock Mar 08 '12 at 05:08
  • I thought about Reflection.... and then i thought I must be crazy. If only i knew how Mr T would do it. ;0 – rism Mar 08 '12 at 05:17