Question

In an asp:TemplateField column of a GridView, I have a LinkButton that passes a command argument to a function that deletes the row when it is clicked. However, after the GridView is sorted, the LinkButton passes the wrong argument. Also, the GridView loses the sort order.

What am I doing wrong?

Here is my code:

<!---master page---->
<asp:GridView runat="server" ID="companies_grid" AllowSorting="true"
    AutoGenerateColumns="false" OnSorting="companies_grid_OnSorting"
    OnRowDataBound="companies_grid_OnRowDataBound" >
        <Columns>
            <%--Company Name--%>
            <asp:TemplateField HeaderText="Company Name" SortExpression="Name">
                <ItemTemplate>
                    <asp:LinkButton ID="LinkButton1" runat="server"
                         OnClick="removeCompany_click" />
                     <a href='<%#Eval("URL")%>'><%#Eval("Name")%></a>
                </ItemTemplate>
             </asp:TemplateField>
            //more columns

<!---code behind---->
    protected void Page_Load(object sender, EventArgs e)
    {
        companies = GetCompanyData();

        companies_grid.DataSource = companies;
        companies_grid.DataBind();
    }

    protected void companies_grid_OnSorting(object sender, GridViewSortEventArgs e)
    {
        //sort is made up of column to sort by + direction
        companies.DefaultView.Sort = e.SortExpression.ToString() + " " + GetSortDirection(e.SortExpression, "companiesExpression", "companiesDirection");
        companies_grid.DataSource = companies;
        companies_grid.DataBind();

    }

    private string GetSortDirection(string column, string expressionViewState, string directionViewState)
    {
        // By default, set the sort direction to ascending.
        string sortDirection = "ASC";

        // Retrieve the last column that was sorted.
        string sortExpression = ViewState[expressionViewState] as string;

        if (sortExpression != null)
        {
            // Check if the same column is being sorted.
            // Otherwise, the default value can be returned.
            if (sortExpression == column)
            {
                string lastDirection = ViewState[directionViewState] as string;
                if ((lastDirection != null) && (lastDirection == "ASC"))
                {
                    sortDirection = "DESC";
                }
            }
        }

        // Save new values in ViewState.
        ViewState[directionViewState] = sortDirection;
        ViewState[expressionViewState] = column;

        return sortDirection;
    }

    protected void companies_grid_OnRowDataBound(Object Sender, GridViewRowEventArgs e)
    {
        GridViewRow currRow = e.Row;

        if (currRow.RowType == DataControlRowType.DataRow)
        {
            LinkButton deleteCompButton = (LinkButton)e.Row.FindControl("LinkButton1") as LinkButton;
            deleteCompButton.CommandArgument = ((DataRowView)e.Row.DataItem)["Company_ID"].ToString();
            deleteCompButton.Text = ((DataRowView)e.Row.DataItem)["Company_ID"].ToString();
        }
    }

    protected void removeCompany_click(Object sender, EventArgs e)
    {
        bool removeSuccess = false;

        string idToDelete = ((LinkButton)sender).CommandArgument as string;
        removeSuccess = UserInfo.DeleteCompany(idToDelete);
        if (removeSuccess)
        {
            Response.Redirect(Request.RawUrl);
        }
    }
Was it helpful?

Solution

Here was the issue:

When the LinkButton is clicked, the first thing that happens is the page reloads. However, Response.Redirect(Request.RawUrl) doesn’t preserve the ViewState, so the sort order is lost. Therefore, the GridView is repopulated with unsorted data.

Then, the LinkButton onClick event function is called. The Object passed in is the LinkButton from the correct row number, but since the sort order of the table had changed (back to its unsorted state), the LinkButton in that row was no longer the LinkButton the user had clicked. Therefore, the command argument was wrong.

To fix the issue:

I changed all the ViewState[string] to Session[string] (so that the sort direction is preserved when the page reloads), and added the following code in the Page_Load function, before the GridView is bound:

if (Session["companiesExpression"] != null 
     && Session["companiesDirection"] != null)
{
     companies.DefaultView.Sort = Session["companiesExpression"] + " " +
          Session["companiesDirection"];
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top