How to Sort on a GridView using ObjectDataSource with TemplateFields

10,048

For sorting functionality to work:

 <asp:GridView GridView ID="GvCountryDetails" AllowPaging="True" 
OnPageIndexChanging="GvCountryDetails_PageIndexChanging" AllowSorting="True" 
onsorting="GvCountryDetails_Sorting">

in .cs file you need to write

protected void GvCountryDetails_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        GvCountryDetails.PageIndex = e.NewPageIndex;
        isPageIndexChanged = true;
        BindData();
    }

protected void GvCountryDetails_Sorting(object sender, GridViewSortEventArgs e)
    {
        sortExpression = e.SortExpression;
        isPageIndexChanged = false;
        BindData();
    }
    private void SortGridData()
    {
        string sSortdir;
        if (isPageIndexChanged == true)
        {
            sSortdir = ViewState["SortDirection"] as string;
        }
        else
        {
            sSortdir = GetSortDirection(sortExpression);
        }

        string sSortExp = sortExpression;

        if (sSortdir == "ASC")
        {
            lstCountryDetails = Sort<Country>(lstCountryDetails, sSortExp, SortDirection.Ascending);
        }
        else
        {
            lstCountryDetails = Sort<Country>(lstCountryDetails, sSortExp, SortDirection.Descending);
        }
    }

    private List<CountryBO> Sort<TKey>(List<CountryBO> list, string sortBy, SortDirection direction)
    {
        PropertyInfo property = list.GetType().GetGenericArguments()[0].GetProperty(sortBy);
        if (direction == SortDirection.Ascending)
        {
            return list.OrderBy(e => property.GetValue(e, null)).ToList<CountryBO>();
        }
        else
        {
            return list.OrderByDescending(e => property.GetValue(e, null)).ToList<Country>();
        }
    }

    private string GetSortDirection(string column)
    {
        string sortDirection = "ASC";
        string sortExpression = ViewState["SortExpression"] as string;
        if (sortExpression != null)
        {
            if (sortExpression == column)
            {
                string lastDirection = ViewState["SortDirection"] as string;
                if ((lastDirection != null) && (lastDirection == "ASC"))
                {
                    sortDirection = "DESC";
                }
            }
        }

        ViewState["SortDirection"] = sortDirection;
        ViewState["SortExpression"] = column;
        return sortDirection;
    }
Share:
10,048
Jonathan Mitchem
Author by

Jonathan Mitchem

Updated on November 19, 2022

Comments

  • Jonathan Mitchem
    Jonathan Mitchem over 1 year

    Background:

    I am working with a GridView and an ObjectDataSource. I am implementing Paging and Sorting.

    On the ObjectDataSource:

            objectDataSource.TypeName = value;
            objectDataSource.SelectMethod = "Select";
            objectDataSource.SelectCountMethod = "SelectCount";
            objectDataSource.SortParameterName = "sortExpression";
            objectDataSource.EnablePaging = true;
    

    On the GridView:

            gridView.AllowPaging = true;
            gridView.AllowSorting = true;
            gridView.DataSource = objectDataSource;
    

    To get paging and sorting to work, I set "EnableSortingAndPagingCallbacks" to True. Before, I was getting a "System.Web.HttpException: The GridView fired event Sorting which wasn't handled." and this fixes it.

    If I use only BoundFields in my GridView, this is great and works fine.

    However, if I used TemplateFields, I get a "NotSupportedException: Callbacks are not supported on TemplateField because some controls cannot update properly in a callback. Turn callbacks off on GridView."

    Which, makes sense. I just need to know how to make sorting work, without using EnableSortingAndPagingCallbacks.

    If EnableSortingAndPagingCallbacks = True:

    • Paging Works
    • Sorting Works
    • BoundFields Work
    • TemplateFields do Not Work

    If EnableSortingAndPagingCallbacks = False:

    • Paging Works
    • Sorting does Not Work
    • BoundFields Work
    • TemplateFields Work

    My Question:

    How do I go about getting Paging, Sorting, and TemplateFields to work, all at the same time?


    Clarification on the implementation:

    Using an ObjectDataSource with a GridView requires implementing a method called Select that provides a sort expression, the number of rows to return, and the start row:

        public IEnumerable<CountyAndStateGridRow> Select(string sortExpression, int maximumRows, int startRowIndex)
        {
            string oql = "select County order by {" + sortExpression + "}" ;
    
            var counties = QueryProvider.ExecuteQuery(oql).Cast<County>();
    
            var page = counties.Skip(startRowIndex).Take(maximumRows);
    
            var rows = page.Select(
                county => new CountyAndStateGridRow
                {
                    CountyName = county.Name,
                    StateName = county.State.Name,
                });
    
            return rows;
        }
    

    The specific SortExpression is defined in the aspx/ascx:

    <Columns>
           <asp:BoundField HeaderText="County Name" DataField="CountyName" SortExpression="Name" />
           <asp:BoundField HeaderText="State Name" DataField="StateName" SortExpression="State.Name" />
    </Columns>
    

    This is supposed to be passed in and call the Select method on the ObjectDataSource when the column is clicked, but it does not seem to work if EnableSortingAndPagingCallbacks = true, and instead I get the exception about the Sorting event not being defined.