Search code examples
c#asp.net

DataView.Sort - more than just asc/desc (need custom sort)


I've got a report being built from a dataset. The dataset uses the Sort property to order the data. I know that I can create a sort expression like this:

"field desc, field2 asc"

But what I need now is a way to do a custom sort. In SQL, I can perform a custom sort by doing something like this:

order by 
    case when field = 'Some Value' then 0 end
    case when field = 'Another Value' then 1 end

To basically re-define my sort (i.e, Some Value comes before Another Value).

Is it possible to do something similar as a sort expression against a DataView?


Solution

  • Ok, I just whipped this up real quick, and didn't do all the neccessary error handling and null checking, but it should give you an idea and should be enough to get you started:

    public static class DataTableExtensions
    {
        public static DataView ApplySort(this DataTable table, Comparison<DataRow> comparison)
        {
    
            DataTable clone = table.Clone();
            List<DataRow> rows = new List<DataRow>();
            foreach (DataRow row in table.Rows)
            {
                rows.Add(row);    
            }
    
            rows.Sort(comparison);
    
            foreach (DataRow row in rows)
            {
                clone.Rows.Add(row.ItemArray);
            }
    
            return clone.DefaultView;
        }
    
    
    }
    

    Usage:

        DataTable table = new DataTable();
        table.Columns.Add("IntValue", typeof(int));
        table.Columns.Add("StringValue");
    
        table.Rows.Add(11, "Eleven");
        table.Rows.Add(14, "Fourteen");
        table.Rows.Add(10, "Ten");
        table.Rows.Add(12, "Twelve");
        table.Rows.Add(13, "Thirteen");
    

    //Sort by StringValue:

     DataView sorted = table.ApplySort((r, r2) =>
            {
                return ((string)r["StringValue"]).CompareTo(((string)r2["StringValue"]));
            });
    

    Result:

    11 Eleven

    14 Fourteen

    10 Ten

    13 Thirteen

    12 Twelve

    //Sort by IntValue:

    DataView sorted = table.ApplySort((r, r2) =>
                {
                    return ((int)r["IntValue"]).CompareTo(((int)r2["IntValue"]));
                });
    

    Result:

    10 Ten

    11 Eleven

    13 Thirteen

    12 Twelve

    14 Fourteen

    EDIT: Changed it to extension method.

    Now in your Lambda, (or you can create a full blown Comparison method) you can do any kind of custom sorting logic that you need. Remember, -1 is less than, 0 is equal to, and 1 is greater than.