CheckBox in GridView firing CheckedChanged event at wrong time

asp.netevent handlinggridview

I have a checkbox in my gridview footer with autopostack=true (which should fire a checkedchanged event), and a linkbutton in my itemtemplate (which should fire the gridview rowcommand event).

Everything has been working fine, until I placed the following code in my gridview rowdatabound (or databound) event:

        for (int i = 0; i < gridCartRows.Columns.Count - 2; i++)
        {
            e.Row.Cells.RemoveAt(0);
        }

        e.Row.Cells[0].ColumnSpan = gridCartRows.Columns.Count - 1; 

Now, when I click my linkbutton, the checkbox checkedchanged event is automatically fired, and then the rowcommand event is fired.

Why is the checkedchanged event being fired when it shouldn't, when I add the above code?

Is there a way to get around this?

Edit

Here's a sample, that reproduces my issue:

    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" ShowFooter="True"
        OnRowCommand="GridView1_RowCommand" OnRowDataBound="GridView1_RowDataBound">
        <Columns>
            <asp:TemplateField HeaderText="Column1">
                <ItemTemplate>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Column2">
                <ItemTemplate>
                    <asp:LinkButton ID="LinkButton1" runat="server" Text="Fire Row Command" CommandName="Fire" />
                </ItemTemplate>
                <FooterTemplate>
                    Footer
                    <asp:CheckBox ID="CheckBox1" runat="server" AutoPostBack="true" OnCheckedChanged="CheckBox1_CheckedChanged" />
                </FooterTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Column3">
                <ItemTemplate>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

Code-behind:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        GridView1.DataSource = new int[5];
        GridView1.DataBind();
    }
}

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.Footer)
    {
        for (int i = 0; i < GridView1.Columns.Count - 2; i++)
        {
            e.Row.Cells.RemoveAt(0);
        }
        e.Row.Cells[0].ColumnSpan = GridView1.Columns.Count - 1;

        ((CheckBox)e.Row.FindControl("CheckBox1")).Checked = true;
    }
}

protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "Fire")
    {
        Response.Write("RowCommand fired.");
    }
}

protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
    Response.Write("CheckBox fired.");
}

Note, I'm setting the CheckBox property to true in the RowDataBound – if I remove this, it works fine. So merging the cells and setting the checkbox property aren't working nicely together.

Best Answer

GridView Control events are stored in viewstate and they can get messed up very easily. Here removing a cell causing to bind different event to link button. Although after postback __EVENTTARGET is LinkButton, wrong method is called and wrong control, event arguments are passed.

I would suggest to hide the cell rather than removing it:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.Footer)
    {
        e.Row.Cells[1].ColumnSpan = GridView1.Columns.Count - 1;
        e.Row.Cells[0].Visible = false;

        ((CheckBox)e.Row.FindControl("CheckBox1")).Checked = true;
    }
}

This will serve the purpose.

Related Topic