0
votes

Having exhausted my google-fu and reviewed several SO questions that had similar headlines but weren't applicable, it's time to post up.

I have an ASP GridView that I want users to be able to sort. As far as I can tell, it's been configured correctly, but the grid is unresponsive when clicking the column headers, and the server-side event handler never gets called. I've checked the browser for javascript errors, but none are recorded. I do see a POST request being issued, and receiving a 200 response. The request and response appear to consist primarily of the ViewState object.

My GridView. Note that it's inside an UpdatePanel, but the behavior is the same when I remove the UpdatePanel

<asp:UpdatePanel runat="server" ID="AssetListUpdatePanel" ChildrenAsTriggers="true" UpdateMode="Conditional" >
    <ContentTemplate>
        <asp:GridView ID="GridViewList" runat="server" AllowPaging="True" AllowSorting="True"
            AutoGenerateColumns="False" EnableModelValidation="True" PageSize="50" DataKeyNames="AssetCode"
            OnRowCommand="GridViewList_RowCommand" BorderColor="#CCCCCC" GridLines="Horizontal" Width="100%"
            OnPageIndexChanging="GridViewList_PageIndexChanging" OnSorting="GridViewList_Sorting" OnRowDataBound="GridViewListRow_DataBound">
            <HeaderStyle HorizontalAlign="Left" />
            <PagerSettings Mode="NumericFirstLast" />
            <AlternatingRowStyle BackColor="#F4F4F4" />
            <Columns>
                <asp:BoundField DataField="AssetCode" HeaderText="ID" ReadOnly="True" SortExpression="AssetCode" />
                <asp:TemplateField HeaderText="Title" SortExpression="Title" ItemStyle-CssClass="wrap">
                    <ItemTemplate>
                        <%# Eval("Title") %><br />
                        <asp:HyperLink CssClass="filename" runat="server" ID="FileLink" Target="_blank" />
                    </ItemTemplate>
                    <ItemStyle CssClass="wrap"></ItemStyle>
                </asp:TemplateField>
                <asp:BoundField DataField="Type" HeaderText="Type" ReadOnly="True" SortExpression="Type">
                    <HeaderStyle HorizontalAlign="Left"></HeaderStyle>
                    <ItemStyle HorizontalAlign="Center"></ItemStyle>
                </asp:BoundField>
                <asp:BoundField DataField="DateCreated" HeaderText="Created" ReadOnly="True" SortExpression="DateCreated">
                    <HeaderStyle HorizontalAlign="Left"></HeaderStyle>
                    <ItemStyle HorizontalAlign="Center"></ItemStyle>
                </asp:BoundField>
                <asp:BoundField DataField="DateModified" HeaderText="Modified" ReadOnly="True" SortExpression="DateModified">
                    <HeaderStyle HorizontalAlign="Left"></HeaderStyle>
                    <ItemStyle HorizontalAlign="Center"></ItemStyle>
            </Columns>
            <RowStyle HorizontalAlign="Left" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" />
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>

I've done the obvious.... set AllowSorting to true, defined an OnSorting event handler, and specified sort expressions for each column.

And my sorting event handler (which, again, is never called):

protected void GridViewList_Sorting(object sender, GridViewSortEventArgs e)
{
    ViewState["page"] = null;

    const string DESC = "DESC";
    const string ASC = "ASC";


    string SortDirection = DESC;
    if (ViewState["sort"] != null && 
        ViewState["sort"].ToString() == e.SortExpression &&
        (ViewState["sortDirection"] == null ||
        ViewState["sortDirection"].ToString() != ASC))
    {
        SortDirection = ASC;
    }

    ViewState["sort"] = e.SortExpression;
    ViewState["sortDirection"] = SortDirection;

    FilterByCriteria();

    //now that the grid is sorted, apply a style to the sorted column to
    //show the sort status and direction.
    var sortedColumnIdx = GetColumnIndex(GridViewList, e.SortExpression);
    var styleName = SortDirection.Equals(DESC) ? "sortdesc" : "sortasc";
    GridViewList.HeaderRow.Cells[sortedColumnIdx].CssClass = styleName;
}

And the grid is re-bound in the FilterByCriteria() method (please don't give me any flak about the nomenclature!)

private void FilterByCriteria()
{
    DataTable dataTable;
    //retrieve data from DB.
    dataTable = ConvertToDataTable(FilteredAssets());
    DataView dataView = new DataView(dataTable);

    // attach dataview to gridview
    GridViewList.DataSource = dataView;

    // bind
    GridViewList.DataBind();
}

I'm clearly missing something fundamental here, but I'm not seeing it. It's probably worth noting that the pagination for this GridView is behaving the same way... which is to say that it isn't. The GridView is unresponsive and the PageIndexChanging handler is never invoked.

1
Instead of wiring up the event handlers in markup, can you try adding them in Page_Init and see if that makes any difference ? - sh1rts
Simply moving the sorting handler to the Page_Init seems to have fixed the problem for both handlers, which is very weird. Do you have any insight into the whys and wherefores? - Daelynn
Not sure why your grid events weren't firing to be honest, but wiring everything up in the code instead of adding event names to the markup has always been my preference with webforms and has always worked for me. - sh1rts

1 Answers

1
votes

You are not sorting data, just updating the sort and sortDirection ViewStates (unless it all happens in FilterByCriteria). But there is probably no actual change to the GridView so it looks as if the sorting Method is never fired.

//get the data again, either from source or ViewState
DataTable dt = getData();
DataTable dt = ViewState["dt"] as DataTable;

//do the sorting
dt.DefaultView.Sort = ViewState["sort"] + " " + ViewState["sortDirection"];

//rebind the data to the gridview
GridView1.DataSource = dt;
GridView1.DataBind();