Menus

Saturday, January 19, 2013

How to add or remove selected rows from one ASP.Net GridView Control to another Gridview



Here I am explaining how to add or remove selected rows from one ASP.Net GridView Control to another in other words copying selected rows to another ASP.Net GridView Control and  removing unselected rows from the another ASP.Net GridView Control
Concept
The concept behind this tutorial is to use a temporary DataTable to maintain the list selected rows or records and then use the DataTable to bind the secondary GridView.
So let us start with the tutorial initially you’ll have to download the Microsoft’s Northwind Sample Database using the link given below
GridView Mark-up
Below is the HTML Mark-up of the ASP.Net GridViews used for this tutorial.
Primary GridView
<asp:GridView ID="gvAll" runat="server"
AutoGenerateColumns = "false" Font-Names = "Arial"
Font-Size = "11pt" AlternatingRowStyle-BackColor = "#C2D69B" 
HeaderStyle-BackColor = "green" AllowPaging ="true"  
OnPageIndexChanging = "OnPaging" PageSize = "10" >
<Columns>
<asp:TemplateField>
    <HeaderTemplate>
      <asp:CheckBox ID="chkAll" runat="server" onclick = "checkAll(this);"
        AutoPostBack = "true"  OnCheckedChanged = "CheckBox_CheckChanged"/>
    </HeaderTemplate>
    <ItemTemplate>
      <asp:CheckBox ID="chk" runat="server" onclick = "Check_Click(this)"
       AutoPostBack = "true"  OnCheckedChanged = "CheckBox_CheckChanged" />
    </ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField = "CustomerID" HeaderText = "Customer ID"
 HtmlEncode = "false" />
<asp:BoundField DataField = "ContactName" HeaderText = "Contact Name"
HtmlEncode = "false" />
<asp:BoundField DataField = "City" HeaderText = "City"
HtmlEncode = "false" />
</Columns>
<AlternatingRowStyle BackColor="#C2D69B"  />
</asp:GridView>

Secondary GridView
<asp:GridView ID="gvSelected" runat="server"
AutoGenerateColumns = "false" Font-Names = "Arial"
Font-Size = "11pt" AlternatingRowStyle-BackColor = "#C2D69B" 
HeaderStyle-BackColor = "green" EmptyDataText = "No Records Selected"  >
<Columns>
   <asp:BoundField DataField = "CustomerID" HeaderText = "Customer ID" />
   <asp:BoundField DataField = "ContactName" HeaderText = "Contact Name" />
   <asp:BoundField DataField = "City" HeaderText = "City" />
 </Columns>
</asp:GridView>

You will notice both the GridViews are similar except that the second GridView does not have Pagination and Checkboxes

Data Binding the ASP.Net GridView control
I have used the Customers table from the Northwind Database for this example. The following function is used to databind the ASP.Net GridView control
C#
private void BindPrimaryGrid()
{
    string constr = ConfigurationManager
                .ConnectionStrings["conString"].ConnectionString;
    string query = " select CustomerID, ContactName, City from customers";
    SqlConnection con = new SqlConnection(constr);
    SqlDataAdapter sda = new SqlDataAdapter(query, con);
    DataTable dt = new DataTable();
    sda.Fill(dt);
    gvAll.DataSource = dt;
    gvAll.DataBind();
}

VB.Net
Private Sub BindPrimaryGrid()
    Dim constr As String = ConfigurationManager _
                    .ConnectionStrings("conString").ConnectionString()
    Dim query As String="select CustomerID, ContactName, City from customers"
    Dim con As New SqlConnection(constr)
    Dim sda As New SqlDataAdapter(query, con)
    Dim dt As New DataTable()
    sda.Fill(dt)
    gvAll.DataSource = dt
    gvAll.DataBind()
End Sub

Maintaining the state of Checkboxes while paging
This is the core part of this example since its job is to keep track of the selected rows irrespective of which page it belongs and also maintain the state of the checkboxes while pagination so that user selections are not lost when he navigates from one page to another.
To facilitate this I have made use of the following two functions
1. GetData
The GetData function simply retrieves the records for which the user has checked the checkbox, adds them to a DataTable and then saves the DataTable to ViewState
C#
private void GetData()
{
    DataTable dt;
    if (ViewState["SelectedRecords"] != null)
        dt = (DataTable)ViewState["SelectedRecords"];
    else
        dt = CreateDataTable();
    CheckBox chkAll = (CheckBox)gvAll.HeaderRow
                        .Cells[0].FindControl("chkAll");
    for (int i = 0; i < gvAll.Rows.Count; i++)
    {
        if (chkAll.Checked)
        {
            dt = AddRow(gvAll.Rows[i], dt);
        }
        else
        {
            CheckBox chk = (CheckBox)gvAll.Rows[i]
                            .Cells[0].FindControl("chk");
            if (chk.Checked)
            {
                dt = AddRow(gvAll.Rows[i], dt);
            }
            else
            {
                dt = RemoveRow(gvAll.Rows[i], dt);
            }
        }
    }
    ViewState["SelectedRecords"] = dt;
}

VB.Net
Private Sub GetData()
   Dim dt As DataTable
   If ViewState("SelectedRecords") IsNot Nothing Then
       dt = DirectCast(ViewState("SelectedRecords"), DataTable)
   Else
       dt = CreateDataTable()
   End If
   Dim chkAll As CheckBox = DirectCast(gvAll.HeaderRow _
                            .Cells(0).FindControl("chkAll"), CheckBox)
   For i As Integer = 0 To gvAll.Rows.Count - 1
       If chkAll.Checked Then
           dt = AddRow(gvAll.Rows(i), dt)
       Else
           Dim chk As CheckBox = DirectCast(gvAll.Rows(i) _
                                .Cells(0).FindControl("chk"), CheckBox)
           If chk.Checked Then
                    dt = AddRow(gvAll.Rows(i), dt)
           Else
                    dt = RemoveRow(gvAll.Rows(i), dt)
           End If
       End If
   Next
   ViewState("SelectedRecords") = dt
End Sub
C#

private void SetData()
    {
        CheckBox chkAll = (CheckBox)gvByNameParent.HeaderRow.Cells[0].FindControl("chkAll");
        chkAll.Checked = true;
        if (ViewState["SelectedRecords"] != null)
        {
            DataTable dt = (DataTable)ViewState["SelectedRecords"];
            for (int i = 0; i < gvByNameParent.Rows.Count; i++)
            {
                CheckBox chk = (CheckBox)gvByNameParent.Rows[i].Cells[0].FindControl("chk");
                if (chk != null)
                {
                    DataRow[] dr = dt.Select("MemberNo='" + gvByNameParent.Rows[i].Cells[1].Text + "'");
                    chk.Checked = dr.Length > 0;
                    if (!chk.Checked)
                    {
                        chkAll.Checked = false;
                    }
                }
            }
        }
    }

VB.Net

Private Sub SetData()
        Dim chkAll As CheckBox = DirectCast(gvAll.HeaderRow.Cells(0).FindControl("chkAll"), CheckBox)
        chkAll.Checked = True
        If ViewState("SelectedRecords") IsNot Nothing Then
            Dim dt As DataTable = DirectCast(ViewState("SelectedRecords"), DataTable)
            For i As Integer = 0 To gvAll.Rows.Count - 1
                Dim chk As CheckBox = DirectCast(gvAll.Rows(i).Cells(0).FindControl("chk"), CheckBox)
                If chk IsNot Nothing Then
                    Dim dr As DataRow() = dt.[Select]("CustomerID = '" & gvAll.Rows(i).Cells(1).Text & "'")
                    chk.Checked = dr.Length > 0
                    If Not chk.Checked Then
                        chkAll.Checked = False
                    End If
                End If
            Next
        End If
    End Sub

The GetData method makes use of the three methods
1. CreateDataTable
2. AddRow
3. RemoveRow

CreateDataTable method
This method simply creates a new object of DataTable creates its schema by adding necessary columns and then returns the DataTable object
C#
private DataTable CreateDataTable()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("CustomerID");
    dt.Columns.Add("ContactName");
    dt.Columns.Add("City");
    dt.AcceptChanges();
    return dt;
}

VB.Net
Private Function CreateDataTable() As DataTable
   Dim dt As New DataTable()
   dt.Columns.Add("CustomerID")
   dt.Columns.Add("ContactName")
   dt.Columns.Add("City")
   dt.AcceptChanges()
   Return dt
End Function

The Column names are same as that of the SQL Server database.

AddRow method
The AddRow method simply adds a new row to the DataTable. It accepts the GridView row and DataTable as parameters, if it the row is not present in the DataTable it adds it and returns the updated DataTable
C#
private DataTable AddRow(GridViewRow gvRow, DataTable dt)
{
    DataRow[] dr = dt.Select("CustomerID = '" + gvRow.Cells[1].Text + "'");
    if (dr.Length <= 0)
    {
        dt.Rows.Add();
        dt.Rows[dt.Rows.Count - 1]["CustomerID"] = gvRow.Cells[1].Text;
        dt.Rows[dt.Rows.Count - 1]["ContactName"] = gvRow.Cells[2].Text;
        dt.Rows[dt.Rows.Count - 1]["City"] = gvRow.Cells[3].Text;
        dt.AcceptChanges();
    }
    return dt;
}

VB.Net
Private Function AddRow(ByVal gvRow As GridViewRow, ByVal dt As DataTable) As DataTable
    Dim dr As DataRow() = dt.Select("CustomerID = '" _
                                    & gvRow.Cells(1).Text & "'")
    If dr.Length <= 0 Then
        dt.Rows.Add()
        dt.Rows(dt.Rows.Count - 1)("CustomerID") = gvRow.Cells(1).Text
        dt.Rows(dt.Rows.Count - 1)("ContactName") = gvRow.Cells(2).Text
        dt.Rows(dt.Rows.Count - 1)("City") = gvRow.Cells(3).Text
        dt.AcceptChanges()
    End If
    Return dt
End Function

RemoveRow method
The RemoveRow method simply removes a row from the DataTable. It accepts the GridView row and DataTable as parameters, if it the row is present in the DataTable it removes  it and returns the updated DataTable
C#
private DataTable RemoveRow(GridViewRow gvRow, DataTable dt)
{
    DataRow[] dr = dt.Select("CustomerID = '" + gvRow.Cells[1].Text + "'");
    if (dr.Length > 0)
    {
        dt.Rows.Remove(dr[0]);
        dt.AcceptChanges();
    }
    return dt;
}

VB.Net
Private Function RemoveRow(ByVal gvRow As GridViewRow, ByVal dt As DataTable) As DataTable
    Dim dr As DataRow() = dt.Select("CustomerID = '" _
                                    & gvRow.Cells(1).Text & "'")
    If dr.Length > 0 Then
       dt.Rows.Remove(dr(0))
       dt.AcceptChanges()
    End If
    Return dt
End Function

GetData method is called up in the OnPageIndexChanging event and also the OnCheckedChanged event in the following way
PageIndexChanging event
C#
protected void OnPaging(object sender, GridViewPageEventArgs e)
{
    GetData();
    gvAll.PageIndex = e.NewPageIndex;
    BindPrimaryGrid();
    SetData();
}

VB.Net
Protected Sub OnPaging(ByVal sender As Object, ByVal e As GridViewPageEventArgs)
    GetData()
    gvAll.PageIndex = e.NewPageIndex
    BindPrimaryGrid()
    SetData()
End Sub

CheckBox OnCheckChanged event
C#
protected void CheckBox_CheckChanged(object sender, EventArgs e)
{
    GetData();
    SetData();
    BindSecondaryGrid();
}

VB.Net
Protected Sub CheckBox_CheckChanged(ByVal sender As Object, ByVal e As EventArgs)
   GetData()
   SetData()
   BindSecondaryGrid()
End Sub

The above event is the one which will get called whenever checkbox is checked or unchecked. I will dynamically add or remove the current selected row in the primary GridView to the secondary GridView thus giving us a Shopping Cart which display the customer what all items are selected by him in the secondary GridView
The above event calls the BindSecondaryGrid function. The job of this function is to simply bind the secondary GridView with the DataTable retrieved from the ViewState
C#
private void BindSecondaryGrid()
{
    DataTable dt = (DataTable)ViewState["SelectedRecords"];
    gvSelected.DataSource = dt;
    gvSelected.DataBind();
}

VB.Net
Private Sub BindSecondaryGrid()
  Dim dt As DataTable = DirectCast(ViewState("SelectedRecords"), DataTable)
  gvSelected.DataSource = dt
  gvSelected.DataBind()
End Sub

Client Side Scripting
I have made use of some JavaScript methods for the Check-all checkbox functionality
Here is Javascrip methods


<script type = "text/javascript">
<!--
    function Check_Click(objRef) {
        //Get the Row based on checkbox
        var row = objRef.parentNode.parentNode;

        //Get the reference of GridView
        var GridView = row.parentNode;

        //Get all input elements in Gridview
        var inputList = GridView.getElementsByTagName("input");

        for (var i = 0; i < inputList.length; i++) {
            //The First element is the Header Checkbox
            var headerCheckBox = inputList[0];

            //Based on all or none checkboxes
            //are checked check/uncheck Header Checkbox
            var checked = true;
            if (inputList[i].type == "checkbox" && inputList[i] != headerCheckBox) {
                if (!inputList[i].checked) {
                    checked = false;
                    break;
                }
            }
        }
        headerCheckBox.checked = checked;

    }
    function checkAll(objRef) {
        var GridView = objRef.parentNode.parentNode.parentNode;
        var inputList = GridView.getElementsByTagName("input");
        for (var i = 0; i < inputList.length; i++) {
            var row = inputList[i].parentNode.parentNode;
            if (inputList[i].type == "checkbox" && objRef != inputList[i]) {
                if (objRef.checked) {
                    inputList[i].checked = true;
                }
                else {
                    if (row.rowIndex % 2 == 0) {
                        row.style.backgroundColor = "#C2D69B";
                    }
                    else {
                        row.style.backgroundColor = "white";
                    }
                    inputList[i].checked = false;
                }
            }
        }
    }
//-->
</script>
   
Screenshots
The screenshot below describes how the selected rows or records are displayed


No comments:

Post a Comment