In this article I will explain with an example, how to delete multiple rows in GridView control in ASP.Net using C# and VB.Net.
This article makes easy to delete multiple rows or records selected by the user using a single button with C# and VB.Net.
 
 

Database

I have made use of the following table Customers with the schema as follows.
Bulk delete multiple rows in ASP.Net GridView control using CheckBoxes
 
I have already inserted few records in the table.
Bulk delete multiple rows in ASP.Net GridView control using CheckBoxes
 
Note: You can download the database table SQL by clicking the download link below.
         Download SQL file
 
 

HTML Markup

The HTML Markup consists of:
GridView – For displaying data.
The GridView consists of three BoundField columns and one TemplateField column.
The TemplateField column consists of a HeaderTemplate and an ItemTemplate with CheckBox control.
CheckBoxes have been assigned with a JavaScript onclick event handler.

Properties

DataKeyNames – For permitting to set the names of the Column Fields, that we want to use in code but do not want to display it. Example Primary Keys, ID fields, etc.
Note: For more details on DataKeyNames, please refer my article DataKeyNames in GridView example in ASP.Net in GridView example in ASP.Net.
 
PageSize – For permitting maximum number of rows to be displayed per page.
AllowPaging – For enabling paging in the GridView control.
 

Events

The GridView has been assigned with the following event handler i.e. OnPageIndexChanging.
 
HiddenField – For capturing CustomerId of the selected customer record.
Button – For deleting records.
The Button has been assigned with an OnClick and OnClientClick event handlers.
<asp:GridView ID="gvCustomers" AutoGenerateColumns="false" runat="server" DataKeyNames="CustomerId"
    AllowPaging="true" OnPageIndexChanging="OnPaging" PageSize="2">
    <Columns>
        <asp:TemplateField>
            <HeaderTemplate>
                <asp:CheckBox ID="chkAll" runat="server" onclick="CheckAll(this);" />
            </HeaderTemplate>
            <ItemTemplate>
                <asp:CheckBox ID="chkRow" runat="server" onclick="CheckRow(this)" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CustomerId" HeaderText="Customer Id" />
        <asp:BoundField DataField="Name" HeaderText="Name" />
        <asp:BoundField DataField="Country" HeaderText="Country" />
    </Columns>
</asp:GridView>
<asp:HiddenField ID="hfCount" runat="server" Value="0" />
<br />
<asp:Button ID="btnDelete" runat="server" Text="Delete Checked Records"
    OnClientClick="returnConfirmDelete();" OnClick="Delete" />
 
 

Client Side Scripting

I have made use of some JavaScript methods for the following
1. Check-all CheckBox functionality.
2. Confirmation before delete functionality.
 

Check-all CheckBox functionality

Note: For more details on Check-all CheckBox functionality, please refer Using JavaScript with ASP.Net GridView Control.
 

Confirmation before delete

Inside the ConfirmDelete function, a FOR loop is executed over all the CheckBoxes and the count of the checked CheckBox are get.
Finally, if the user presses OK delete operation will be performed along with appropriate message.
<script type="text/javascript">
    function ConfirmDelete() {
        var count = document.getElementById("<%hfCount.ClientID %>").value;
        var gv document.getElementById("<%gvCustomers.ClientID%>");
        var chk gv.getElementsByTagName("input");
        for (var i = 0; i < chk.length; i++) {
            if (chk[i].checked && chk[i].id.indexOf("chkAll") == -1) {
                count++;
            }
        }
        if (count == 0) {
            alert("No records to delete.");
            return false;
        }
        else {
            return confirm("Do you want to delete " + count + " records.");
        }
    };
</script>
 
 

Populating GridView with records from the Database

Inside the Page Load event handler, the GetData and BindGrid methods are called.
Inside the BindGrid method, the GridView is populated with the records from the Customers table of SQL Server database.
Note: The GetData method is used to retrieve the record for which the user has checked the CheckBox which will be discussed later in this article.
 
C#
protected void Page_Load(object sender, EventArgs e)
{
    if (this.IsPostBack)
    {
        this.GetData();
    }
    else
    {
        this.BindGrid();
    }
}
 
private void BindGrid()
{
    string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    string query = "SELECT * FROM Customers";
    using (SqlConnection con = new SqlConnection(constr))
    {
        using (SqlDataAdapter sda = new SqlDataAdapter(query, con))
        {
            using (DataTable dt = new DataTable())
            {
                sda.Fill(dt);
                gvCustomers.DataSource = dt;
                gvCustomers.DataBind();
            }
        }
    }
}
 
VB.Net
Protected Sub Page_Load(ByVal sender As ObjectByVal e As EventArgs) Handles Me.Load
    If Me.IsPostBack Then
        Me.GetData()
    Else
        Me.BindGrid()
    End If
End Sub
 
Private Sub BindGrid()
    Dim constr As String ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Dim query As String "SELECT * FROM Customers"
    Using  con As SqlConnection = New SqlConnection(constr)
        Using sda As SqlDataAdapter = New SqlDataAdapter(query, con)
            Using dt As DataTable =  New DataTable()
                sda.Fill(dt)
                gvCustomers.DataSource = dt
                gvCustomers.DataBind()
            End Using
        End Using
    End Using
End Sub
 
 

Maintaining the state of CheckBoxes while paging

GetData Method

The GetData function simply retrieves the records for which the user has checked the CheckBoxes, adds them to an ArrayList and then saves the ArrayList to ViewState.
Inside the GetData method, an object of ArrayList class is created and ViewState is checked for NULL and if it is not NULL then, the value of the ViewState as ArrayList is stored in the object of ArrayList.
Then, the HeaderRow CheckBox control is referenced and a FOR loop is executed over the GridView rows and if the HeaderRow CheckBox is checked, the CustomerId of the all records is stored in the ArrayList object.
If HeaderRow CheckBox is unchecked, then DataRow CheckBox is referenced and a check is performed if GridView row CheckBox is checked, the CustomerId for which the CheckBox is checked is added in the ArrayList object else removed if exists in the ArrayList.
Finally, the object of ArrayList class is set to the ViewState.
C#
private void GetData()
{
    ArrayList arr = new ArrayList();
    if (ViewState["SelectedRecords"] !=  null)
    {
        arr = (ArrayList)ViewState["SelectedRecords"];
    }
 
    CheckBox chkAll = (CheckBox)gvCustomers.HeaderRow.Cells[0].FindControl("chkAll");
    for (int  i = 0; i <gvCustomers.Rows.Count; i++)
    {
        if (chkAll.Checked)
        {
            if (!arr.Contains(gvCustomers.DataKeys[i].Value))
            {
                arr.Add(gvCustomers.DataKeys[i].Value);
            }
        }
        else
        {
            CheckBox chk = (CheckBox)gvCustomers.Rows[i].Cells[0].FindControl("chkRow");
            if (chk.Checked)
            {
                if (!arr.Contains(gvCustomers.DataKeys[i].Value))
                {
                    arr.Add(gvCustomers.DataKeys[i].Value);
                }
            }
            else
            {
                if (arr.Contains(gvCustomers.DataKeys[i].Value))
                {
                    arr.Remove(gvCustomers.DataKeys[i].Value);
                }
            }
        }
    }
    ViewState["SelectedRecords"] = arr;
}
 
VB.Net
Private Sub GetData()
    Dim arr As ArrayList = New ArrayList()
    If ViewState("SelectedRecords")IsNot Nothing Then
        arr = CType(ViewState("SelectedRecords"),ArrayList)
    End If
    Dim chkAll As CheckBox  = CType(gvCustomers.HeaderRow.Cells(0).FindControl("chkAll"),CheckBox)
    For i As Integer = 0 To gvCustomers.Rows.Count - 1
        If chkAll.Checked Then
            If Not arr.Contains(gvCustomers.DataKeys(i).Value) Then
                arr.Add(gvCustomers.DataKeys(i).Value)
            End If
        Else
            Dim chk As CheckBox = CType(gvCustomers.Rows(i).Cells(0).FindControl("chkRow"),CheckBox)
            If chk.Checked Then
                If Not arr.Contains(gvCustomers.DataKeys(i).Value) Then
                    arr.Add(gvCustomers.DataKeys(i).Value)
                End If
            Else
                If arr.Contains(gvCustomers.DataKeys(i).Value) Then
                    arr.Remove(gvCustomers.DataKeys(i).Value)
                End If
            End If
        End If
    Next
    ViewState("SelectedRecords") = arr
End Sub
 

SetData Method

The SetData method simply restores the saved state of the CheckBoxes from the ViewState to HiddenField.
Inside the SetData method, an object of ArrayList class is created and the value of the ViewState as ArrayList is stored in the object of ArrayList.
Then, the HeaderRow CheckBox control is referenced and a FOR loop is executed over the GridView rows and DataRow CheckBox is referenced and a check is performed if GridView row CheckBox is unchecked, then the CheckBox is checked if ArrayList contains the Checked row CustomerId and checked count is set.
Finally, checked CheckBoxes count is set in the HiddenField.
C#
private void SetData()
{
    int currentCount = 0;
    CheckBox chkAll = (CheckBox)gvCustomers.HeaderRow.Cells[0].FindControl("chkAll");
    chkAll.Checked = true;
    ArrayList arr = (ArrayList)ViewState["SelectedRecords"];
    for (int i = 0; i < gvCustomers.Rows.Count; i++)
    {
        CheckBox chk = (CheckBox)gvCustomers.Rows[i].Cells[0].FindControl("chkRow");
        if (chk != null)
        {
            chk.Checked arr.Contains(gvCustomers.DataKeys[i].Value);
            if (!chk.Checked)
            {
                chkAll.Checked = false;
            }
            else
            {
                currentCount++;
            }
        }
    }
    hfCount.Value = (arr.Count - currentCount).ToString();
}
 
VB.Net
Private Sub SetData()
    Dim currentCount As Integer = 0
    Dim chkAll As CheckBox = CType(gvCustomers.HeaderRow.Cells(0).FindControl("chkAll"), CheckBox)
    chkAll.Checked = True
    Dim arr As ArrayList = CType(ViewState("SelectedRecords"),ArrayList)
    For i As Integer = 0 To gvCustomers.Rows.Count - 1
        Dim chk As CheckBox = CType(gvCustomers.Rows(i).Cells(0).FindControl("chkRow"), CheckBox)
        If chk IsNot Nothing Then
            chk.Checked arr.Contains(gvCustomers.DataKeys(i).Value)
            If Not chk.Checked Then
                chkAll.Checked = False
            Else
                currentCount += 1
            End If
        End If
    Next
    hfCount.Value = (arr.Count - currentCount).ToString()
End Sub
 
 

Implementing Paging

Inside the OnPageIndexChanging event handler, the PageIndex property of the GridView is updated with the new Page Number which was clicked.
Finally, the GridView is populated using the BindGrid method which in-turn displays the new GridView page and SetData method is called.
C#
protected void OnPaging(object sender, GridViewPageEventArgs e)
{
    gvCustomers.PageIndex e.NewPageIndex;
    gvCustomers.DataBind();
    this.BindGrid();
    this.SetData();
}
 
VB.Net
Protected Sub OnPaging(ByVal sender As ObjectByVal e As GridViewPageEventArgs)
    gvCustomers.PageIndex e.NewPageIndex
    gvCustomers.DataBind()
    Me.BindGrid()
    Me.SetData()
End Sub
 
 

DeleteRecord Method

Inside the DeleteRecord method, the DELETE query is passed as parameter to SqlCommand class and CustomerId is added as parameter.
Then, the DELETE query is executed using ExecuteNonQuery method of SqlCommand class and the record is deleted from the database.
Note: For more details on how to use ExecuteNonQuery function, please refer Understanding SqlCommand ExecuteNonQuery in C# and VB.Net ExecuteNonQuery in C# and VB.Net.
 
C#
private void DeleteRecord(string customerId)
{
    string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    string query = "DELETE FROM Customers WHERE CustomerId = @CustomerId";
    using (SqlConnection  con =  new SqlConnection(constr))
    {
        using (SqlCommand cmd = new SqlCommand(query, con))
        {
            cmd.Parameters.AddWithValue("@CustomerId",customerId);
            con.Open();
            cmd.ExecuteNonQuery();
            con.Close();
        }
    }
}
 
VB.Net
Private Sub DeleteRecord(ByVal customerId As String)
    Dim constr As String ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Dim query As String "DELETE FROM Customers WHERE CustomerId = @CustomerId"
    Using con As SqlConnection = New SqlConnection(constr)
        Using cmd As SqlCommand = New SqlCommand(query, con)
            cmd.Parameters.AddWithValue("@CustomerId", customerId )
            con.Open()
            cmd.ExecuteNonQuery()
            con.Close()
        End Using
    End Using
End Sub
 
 

Deleting the selected record

When Delete button is clicked, the BindGrid and SetData methods are called.
Note: The BindGrid and SetData methods are already discussed earlier in this article.
 
The AllowPaging property of the GridView is set to false and GridView is again populated.
Next, an object of ArrayList is created and the ViewState is assigned to it.
Then, a FOR loop is executed over the GridView rows and if object of ArrayList contains CustomerId, DeleteRecord method is called and CustomerId of the selected record is passed as parameter and the CustomerId stored in the object of ArrayList is removed.
After that, the object of the ArrayList is set to ViewState and HiddenField value is set to zero.
Finally, the AllowPaging property of the GridView is set to true and GridView is again populated and the count of the deleted record is displayed in JavaScript Alert Message Box using RegisterStartupScript method.
C#
protected void Delete(object sender, EventArgs e)
{
    int count = 0;
    this.BindGrid();
    this.SetData();
    gvCustomers.AllowPaging = false;
    gvCustomers.DataBind();
    ArrayList arr = (ArrayList)ViewState["SelectedRecords"];
     count = arr.Count;
    for (int  i = 0; i < gvCustomers.Rows.Count; i++)
    {
        if (arr.Contains(gvCustomers.DataKeys[i].Value))
        {
            this.DeleteRecord(gvCustomers.DataKeys[i].Value.ToString());
            arr.Remove(gvCustomers.DataKeys[i].Value);
        }
    }
    ViewState["SelectedRecords"] = arr;
    hfCount.Value "0";
    gvCustomers.AllowPaging = true;
    this.BindGrid();
    ClientScript.RegisterStartupScript(this.GetType(), "alert""alert('" + count + " records deleted.');"true);
}
 
VB.Net
Protected Sub Delete(ByVal sender As ObjectByVal e As EventArgs)
    Dim count As Integer = 0
    Me.BindGrid()
    Me.SetData()
    gvCustomers.AllowPaging = False
    gvCustomers.DataBind()
    Dim arr As ArrayList = CType(ViewState("SelectedRecords"), ArrayList)
     count = arr.Count
    For i As Integer = 0 To gvCustomers.Rows.Count - 1
        If arr.Contains(gvCustomers.DataKeys(i).Value) Then
            Me.DeleteRecord(gvCustomers.DataKeys(i).Value.ToString())
            arr.Remove(gvCustomers.DataKeys(i).Value)
        End If
    Next
    ViewState("SelectedRecords") = arr
    hfCount.Value "0"
    gvCustomers.AllowPaging = True
    Me.BindGrid()
    ClientScript.RegisterStartupScript(Me.GetType(), "alert""alert('" & count & " records deleted.');"True)
End Sub
 
 

Screenshot

Bulk delete multiple rows in ASP.Net GridView control using CheckBoxes
 
 

Downloads