madcolor
madcolor

Reputation: 8170

Hierarchical (Multi-column) Sorting for the .net GridView?

Is there a simple ".Net" way to do hierarchical sorting

Table...

A|B|C
-----
1|2|5
2|8|4
2|4|3
3|7|2
4|4|1

clicking on A, then B would get you..

A|B|C
-----
1|2|5
2|4|3
2|8|4
3|7|2
4|4|1

The change being that I'm sorting (B) in context of (A) and so forth.

Obviously this could be managed in the datasource, but was wondering if someone has a elegant and scalable solution.. thanks.

Upvotes: 1

Views: 4888

Answers (3)

In order to get an ASP.NET GridView to correctly sort when multiple columns are listed in a BoundField's Sort specification, you need to bind the grid's OnSorting event to this function:

protected void gridViewSorting(object sender, GridViewSortEventArgs e)
{
    //
    // This odd function permits GridView objects to sort on multiple columns
    // Without this function, a GridView object does not sort correctly when multiple
    // columns are named in its sort specification.
    //

    if (!(sender is GridView))
    {
        return;
    }
    if (!e.SortExpression.Contains(','))
    {
        return;
    }

    GridView gv = sender as GridView;

    //
    // Find the column that is to become the basis of the sort
    //
    foreach (DataControlField dc in gv.Columns)
    {
        String fieldSortExprClean = dc.SortExpression.Replace(" DESC", "");
        fieldSortExprClean = fieldSortExprClean.Replace(" ASC", "");

        String eventSortExprClean = e.SortExpression.Replace(" DESC", "");
        eventSortExprClean = eventSortExprClean.Replace(" ASC", "");

        if (fieldSortExprClean == eventSortExprClean)
        {
            if (e.SortDirection == SortDirection.Ascending)
            {
                dc.SortExpression = fieldSortExprClean.Replace(",", " ASC,");
                e.SortExpression = fieldSortExprClean.Replace(",", " ASC,");
            }
            else
            {
                dc.SortExpression = fieldSortExprClean.Replace(",", " DESC,");
                e.SortExpression = fieldSortExprClean.Replace(",", " DESC,");
            }
        }
    }
}

Upvotes: 2

Jeff Sternal
Jeff Sternal

Reputation: 48623

If you're asking about doing it in conjunction with paging, there's no simple and scalable solution. In fact, that is kind of a holy grail of business application web development. See, for example, the StackOverflow question Dynamic Sorting within SQL Stored Procedures, which concerns the same thing. After all, if we had dynamic sorting on our database servers, we would only have to code the mechanism for managing the user's sort choices.

You really only have three options for multi-column sorts:

  • Do it in the client, letting your data container do the heavy lifting (when you're using a data container that has this functionality built in, like System.Data.DataView).

  • Write your own algorithm and sort the data yourself before binding.

  • Do it at the database server via one of the solutions discussed in the link above.

Neither of the client-side solutions are really scalable since they involve pulling and delivering all your data when you may only need a subset.

Upvotes: 2

Michael Kniskern
Michael Kniskern

Reputation: 25280

ASPX page

<asp:GridView id="MyGridView" runat="server" AllowSorting="true" OnSorting="MyGridView_OnSorting">
    <asp:BoundField DataField="ColumnA" SortExpression="A" />
    <asp:BoundField DataField="ColumnB" SortExpression="B" />
    <asp:BoundField DataField="ColumnC" SortExpression="C" />
</asp:GridView>

Code Behind

protected void MyGridView_OnSorting(object sender, GridViewSortEventArgs e)
{
    List<MyEntity> data = MyBLL.GetDataSource();

    data.Sort(delegate(MyEntity x, MyEntity y) {
        switch(e.SortExpression)
        {
            case "ColumnA":
               return String.Compare(x.ColumnA, y.ColumnA);
               break;
            case "ColumnB":
               return String.Compare(x.ColumnB, y.ColumnB);
               break;
            case "ColumnC":
               return String.Compare(x.ColumnC, y.ColumnC);
               break;
        }
    }
    );

    MyGridView.DataSource = data;
    MyGridView.DataBind();
}

Upvotes: 0

Related Questions