This is a migrated thread and some comments may be shown as answers.

Collecting the Data for a Custom Sort

5 Answers 89 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Stuart Hemming
Top achievements
Rank 2
Stuart Hemming asked on 09 Sep 2010, 10:55 PM
I need to implement a Custom Sort on a grid.

To do this, I need to pass the sort criteria to my Data Access Layer. I thought that the args for the SortCommand would provide me with what I need, but they only detail the column currently being sorted. I expected to discover in this object all of the sorted columns and their current sort order (to be clear, my grid allows multi-column sorting).

I then thought that I might be able to use the Grid.MasterTableView.SortExpressions collection, but that shows the old sort expressions.

Am I right in thinking that I have to manually create the current sort expressions collection from the old one and the args of the SortCommand event handler if I want the full sort expression for the grid?

-- 
Stuart

5 Answers, 1 is accepted

Sort by
0
Stuart Hemming
Top achievements
Rank 2
answered on 10 Sep 2010, 01:02 PM
I couldn't find anything that suggested I should be able to get at the new, full set, of Sort Expressions, so I wrote this ...
string GenerateOrderByExpression(GridTableView RadGridTableToSort, GridSortCommandEventArgs SortCommandArgs)
{
    List<GridSortExpression> sort = new List<GridSortExpression>();
    foreach (GridSortExpression x in RadGridTableToSort.SortExpressions)
    {
        sort.Add(new GridSortExpression { FieldName = x.FieldName, SortOrder = x.SortOrder });
    }
 
    GridSortExpression sortExp = sort.FirstOrDefault(exp => exp.FieldName == SortCommandArgs.SortExpression);
    if (sortExp != null)
    {
        if (SortCommandArgs.NewSortOrder == GridSortOrder.None)
        {
            sort.Remove(sortExp);
        }
        else
        {
            sortExp.SortOrder = SortCommandArgs.NewSortOrder;
        }
    }
    else
    {
        if (SortCommandArgs.NewSortOrder != GridSortOrder.None)
        {
            sort.Add(new GridSortExpression { FieldName = SortCommandArgs.SortExpression, SortOrder = SortCommandArgs.NewSortOrder });
        }
    }
    return GetSortExpressionString(sort);
}
string GetSortExpressionString(List<GridSortExpression> SortExpressions)
{
    StringBuilder sb = new StringBuilder();
    bool first = true;
    SortExpressions.ForEach(exp =>
    {
        if (first)
        {
            first = false;
        }
        else
        {
            sb.Append(", ");
        }
 
        sb.Append(String.Format("{0} {1}", exp.FieldName, exp.SortOrderAsString()));
    });
    return sb.ToString();
}

In my implementation, I'm getting the Sort Expressions as a string and passing 'em to an extension method of IEnumerable<T> that I found on this page. This is used to sort the data and is called like this ...
protected void RadGrid1_SortCommand(object sender, GridSortCommandEventArgs e)
{
    string orderbyExpression = GenerateOrderByExpression(RadGrid1.MasterTableView, e);
    e.Item.OwnerTableView.DataSource = data.OrderBy(orderbyExpression);
    e.Item.OwnerTableView.Rebind();
}

I'd be interested in any comments anyone has about this, especially wrt my original question.

-- 
Stuart

0
Veli
Telerik team
answered on 13 Sep 2010, 12:02 PM
Hi Stuart,

RadGrid automatically updates and keeps track of the sort expressions when you fire the sort command. You need to take into consideration both the current RadGrid.MasterTableView.SortExpressions and data in the GridSortCommandEventArgs, but you should not modify the current RadGrid.MasterTableView.SortExpression collection. It will be modified automatically by RadGrid.

So, if you need to generate an SQL OrderBy clause from inside the SortCommand event handler in RadGrid, you can use the following helper function:

public static class RadGridHelper
{
    public static string GetOrderByExpression(GridSortCommandEventArgs e)
    {
        string orderBy = String.Empty;
        GridTableView sortedTable = e.Item.OwnerTableView;
 
        foreach (GridSortExpression expr in sortedTable.SortExpressions)
        {
            if (expr.FieldName != e.SortExpression)
            {
                orderBy += expr.FieldName + " " + expr.SortOrderAsString() + ",";
            }
        }
 
        if (e.NewSortOrder != GridSortOrder.None)
        {
            orderBy += e.SortExpression + " " + GridSortExpression.SortOrderAsString(e.NewSortOrder);
        }
        else if (orderBy.EndsWith(","))
        {
            orderBy = orderBy.Remove(orderBy.LastIndexOf(","), 1);
        }
 
        return orderBy;
    }
}

With the above helper class, you can generate the OrderBy clause representing the current sort expressions (including the new sort command parameters):

protected void RadGrid1_SortCommand(object sender, GridSortCommandEventArgs e)
{
    string orderByString = RadGridHelper.GetOrderByExpression(e);
}

Note that I do not make any changes to the SortExpressions collection of the respective GridTableView. I only access its items. The collection itself will be updated automatically.

Greetings,
Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Stuart Hemming
Top achievements
Rank 2
answered on 13 Sep 2010, 12:51 PM
Veli,

Thanks for that. I'll have a go which that which you've posted here. Of course, the goal posts have moved a little now and I need to ensure that I always include  a default order in the sort except where the user's selected sort already includes it.

However, thanks for your help.

-- 
Stuart
0
Stuart Hemming
Top achievements
Rank 2
answered on 13 Sep 2010, 05:19 PM
Veli,

I had a play with this and it doesn't work, or rather it doesn't work like you'd expect.

If you have multi-column sorting enabled and you sort first by columnA and then by columnB, your code, naturally, returns a sort key of "columnA ASC, columnB ASC". Now click on columnA to reverse the sort of that column and you would expect to get "columnA DESC, columnB ASC", what you actually get is "columnB ASC, columnA DESC" which is a whole different animal.

And as I've said I now have to include a default sort too and that adds to the complexity of the issue.

Incidentally, I tried to post a reply to your comment about the Code Library article I submitted but there isn't an obvious mechanism for doing so. How can I discuss this with you?

-- 
Stuart
0
Veli
Telerik team
answered on 14 Sep 2010, 09:04 AM
Hello Stuart,

You are right, a switch from ASC to DESC and vise versa should not change the position of the orderby field in the string. Only a newly added field should go at the end. Here is the modified code to support that:

public static class RadGridHelper
{
    public static string GetOrderByExpression(GridSortCommandEventArgs e)
    {
        GridTableView sortedTable = e.Item.OwnerTableView;
        List<string> orderByFields = new List<string>();
        bool appendToEnd = true;
 
        foreach (GridSortExpression expr in sortedTable.SortExpressions)
        {
            if (expr.FieldName != e.SortExpression)
            {
                orderByFields.Add(expr.FieldName + " " + expr.SortOrderAsString());
            }
            else
            {
                appendToEnd = false;
                if (e.NewSortOrder != GridSortOrder.None)
                {
                    orderByFields.Add(expr.FieldName + " " + GridSortExpression.SortOrderAsString(e.NewSortOrder));
                }
            }
        }
 
        if (e.NewSortOrder != GridSortOrder.None && appendToEnd)
        {
            orderByFields.Add(e.SortExpression + " " + GridSortExpression.SortOrderAsString(e.NewSortOrder));
        }
         
        return String.Join(",", orderByFields.ToArray());
    }
}


I have updated the Code Library entry and you should be able to post in it now. Still, I believe continuing the discussion in this forum thread would be most beneficial for the community, so that other members can share opinions too.

Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
Grid
Asked by
Stuart Hemming
Top achievements
Rank 2
Answers by
Stuart Hemming
Top achievements
Rank 2
Veli
Telerik team
Share this question
or