jQuery & JavaScript

Check or uncheck all CheckBoxes in an ASP.NET GridView with jQuery

jQuery & JavaScript · · Published 2026-10-01

A check box in the header that selects every row is standard in admin grids. In Web Forms the boxes are server controls inside a TemplateField; jQuery handles the clicking in the browser, and the server reads the result on postback as usual.

Markup

<asp:GridView ID="gvMail" runat="server" AutoGenerateColumns="false" DataKeyNames="MessageId" CssClass="grid">
    <Columns>
        <asp:TemplateField>
            <HeaderTemplate>
                <asp:CheckBox ID="chkAll" runat="server" CssClass="check-all" ToolTip="Select all" />
            </HeaderTemplate>
            <ItemTemplate>
                <asp:CheckBox ID="chkRow" runat="server" CssClass="check-row" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="Subject" HeaderText="Subject" />
        <asp:BoundField DataField="Received" HeaderText="Received" DataFormatString="{0:g}" />
    </Columns>
</asp:GridView>
<asp:Button ID="btnDelete" runat="server" Text="Delete selected" OnClick="btnDelete_Click" />

An asp:CheckBox renders the CssClass on a <span> that wraps the <input>, not on the input itself. The selectors below therefore look for the input inside the span: .check-row input.

jQuery

$(function () {
  var $grid = $(".grid");

  function rows() { return $grid.find(".check-row input[type=checkbox]"); }
  function header() { return $grid.find(".check-all input[type=checkbox]"); }

  // header -> rows
  $grid.on("change", ".check-all input", function () {
    rows().prop("checked", this.checked);
    header().prop("indeterminate", false);
  });

  // rows -> header
  $grid.on("change", ".check-row input", function () {
    var total = rows().length, checked = rows().filter(":checked").length;
    header().prop({ checked: total > 0 && checked === total,
                    indeterminate: checked > 0 && checked < total });
  });
});

The indeterminate property shows a dash in the header box when only some rows are selected. It is a visual state only: it is never posted, and the server sees the header box as unchecked.

Reading the selection on the server

protected void btnDelete_Click(object sender, EventArgs e)
{
    var ids = new List<int>();
    foreach (GridViewRow row in gvMail.Rows)
    {
        if (row.RowType != DataControlRowType.DataRow) continue;
        var chk = (CheckBox)row.FindControl("chkRow");
        if (chk.Checked) ids.Add((int)gvMail.DataKeys[row.RowIndex].Value);
    }
    if (ids.Count == 0) return;
    MailRepository.Delete(ids);   // one parameterised statement, or a table-valued parameter
    BindGrid();
}

Check boxes changed by script are posted like any others, so chk.Checked reflects what the user sees. Bind the grid only when !IsPostBack in Page_Load, otherwise the boxes are recreated unchecked before the click handler runs. Deleting a list of ids in one call is shown in Passing a DataTable as a table-valued parameter.

Variations

Common mistakes

Official documentation