Introduction
The problem can be stated as follows:
- There should be a checkbox in the header to check all and uncheck all.
- There should be checkboxes with individual records to select the records individually.
- The check all check box on the header should be checked if all the records are individually selected.
- There should be an external button outside the
DataGrid
by which we should be able to retrieve checked records.
Solution
The records that are retrieved in the DataGrid
is from a table which I have created. The script for creating the table in SQL Server is as follows:
CREATE TABLE [dbo].[Anz_Contacts] (
[Id] [int] IDENTITY (1, 1) NOT NULL ,
[FirstName] [char] (10) NULL ,
[LastName] [char] (10) NULL ,
[Designation] [varchar] (50) NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Anz_Contacts] WITH NOCHECK ADD
CONSTRAINT [PK_Anz_Contacts] PRIMARY KEY CLUSTERED
(
[Id]
) ON [PRIMARY]
GO
On the Page_Load
event, the DataGrid
is bound to the table. The code for binding DataGrid
is shown below:
Note: Change the connection string which suits your DBMS, cnnDB
and myDataGrid
are protected member variables.
private void Page_Load(object sender, System.EventArgs e)
{
cnnDB = new SqlConnection("server=HOME;user id=sa;password=;database=Contacts");
if (!IsPostBack)
bindGrid();
}
private void bindGrid()
{
SqlDataAdapter da = new SqlDataAdapter("select * from Anz_Contacts",cnnDB);
DataSet ds = new DataSet();
da.Fill(ds, "Employees");
myDataGrid.DataSource=ds.Tables["Employees"].DefaultView;
myDataGrid.DataBind();
}
Now that we have seen how we bind the data to the grid, we will look at how the HTML of the DataGrid
looks like:
<form id="Form1" name="Form1" method="post" runat="server">
<ASP:DATAGRID id="myDataGrid"
runat="server"
AutoGenerateColumns="false"
HeaderStyle-BackColor="#aaaadd"
Font-Size="8pt"
Font-Name="Verdana"
CellSpacing="0"
CellPadding="3"
ShowFooter="true"
BorderColor="Black"
BackColor="AntiqueWhite"
Width="600">
<HeaderStyle BackColor="NavajoWhite"></HeaderStyle>
<FooterStyle BackColor="NavajoWhite"></FooterStyle>
<Columns>
<asp:TemplateColumn HeaderText="contract">
<HeaderTemplate>
<input type="checkbox" id="checkAll"
onclick="CheckAll(this);" runat="server" name="checkAll">
</HeaderTemplate>
<ItemTemplate>
<input type="checkbox" runat="server" id="EmpId"
onclick="CheckChanged();" checked='false' name="EmpId" />
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Id">
<ItemTemplate>
<asp:Label id="Id" Text='<%#
DataBinder.Eval(Container.DataItem, "Id") %>' runat="server" />
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="FirstName"
HeaderText="FirstName"></asp:BoundColumn>
<asp:BoundColumn DataField="LastName"
HeaderText="LastName"></asp:BoundColumn>
<asp:BoundColumn DataField="Designation"
HeaderText="Designation"></asp:BoundColumn>
</Columns>
</ASP:DATAGRID>
</form >
Notice the TemplateColumn
in the DataGrid
. TemplateColumn
represents a column type for the DataGrid
control that allows you to customize the layout of controls in the column. I have used the template column to render check boxes in the header and the item templates. I have used the HtmlInputCheckBox
control rather than a <asp:CheckBox>
control. This is because the checking and unchecking is strictly a client side process and there is no need for server side manipulation here. The checkbox in the header will call the client script function CheckAll()
when it is clicked, and the checkbox in the record items will call CheckChanged()
function.
I have used the second TemplateColumn
to include a Label
control to display the ID column from the table. This Label
control will help us later to get the ID of the selected records. The rest of the columns are bound with FirstName
, LastName
and Designation
using the BoundColumn
of DataGrid
.
Now we will take a look at the client side JavaScript functions to manipulate the checking and unchecking.
If we are using VS.NET and a code behind model, it is preferable to use the RegisterClientScriptBlock
method of the page to emit client-side script blocks in the page. The client script registering is done when the page is loaded. So we can write the code for it on the Page_load
event of the page.
The JavaScript function CheckAll()
is as follows. I have constructed the script string using string concatenation, for readability. You can use the StringBuilder
class for more efficient concatenation.
string strScript;
strScript= " <script language="JavaScript"> ";
strScript+=" function CheckAll( checkAllBox ) ";
strScript+=" { ";
strScript+=" var frm = document.Form1; ";
strScript+=" var ChkState=checkAllBox.checked; ";
strScript+=" for(i=0;i< frm.length;i++) ";
strScript+=" { ";
strScript+=" e=frm.elements[i]; ";
strScript+=" if(e.type=='checkbox' && e.name.indexOf('Id') != -1)";
strScript+=" e.checked= ChkState ; ";
strScript+=" } ";
strScript+=" } ";
strScript+=" </script> ";
if(!this.IsClientScriptBlockRegistered("clientScriptCheckAll"))
this.RegisterClientScriptBlock("clientScriptCheckAll", strScript);
In the above script, we first checked the state of the CheckBox
that fired the event, i.e., the header CheckBox
. Next, we loop through the form elements searching for all CheckBox
controls which have the word "Id" in their name to set the value of the CheckBox
es to match that of the Header CheckBox
.
The JavaScript function which is called when the checkboxes in each record item is checked or unchecked is as follows. Here we are checking whether all the records are selected or not to determine the checked state of the checkAll
checkbox in the header.
strScript="";
strScript= "<script language="JavaScript"> ";
strScript+="function CheckChanged() ";
strScript+="{ ";
strScript+=" var frm = document.Form1; ";
strScript+=" var boolAllChecked; ";
strScript+=" boolAllChecked=true; ";
strScript+=" for(i=0;i< frm.length;i++) ";
strScript+=" { ";
strScript+=" e=frm.elements[i]; ";
strScript+=" if ( e.type=='checkbox' && e.name.indexOf('Id') != -1 )";
strScript+=" if(e.checked== false) ";
strScript+=" { ";
strScript+=" boolAllChecked=false; ";
strScript+=" break; ";
strScript+=" } ";
strScript+=" } ";
strScript+=" for(i=0;i< frm.length;i++) ";
strScript+=" { ";
strScript+=" e=frm.elements[i]; ";
strScript+=" if ( e.type=='checkbox' && e.name.indexOf('checkAll') != -1 )";
strScript+=" { ";
strScript+=" if( boolAllChecked==false) ";
strScript+=" e.checked= false ; ";
strScript+=" else ";
strScript+=" e.checked= true; ";
strScript+=" break; ";
strScript+=" } ";
strScript+=" } ";
strScript+=" } ";
strScript+=" </script> ";
if(!this.IsClientScriptBlockRegistered("clientScriptCheckChanged"))
this.RegisterClientScriptBlock("clientScriptCheckChanged", strScript);
Now, what is left is to use an external button outside the DataGrid
for retrieving checked records. Add this code inside the form which contains the DataGrid
:
<asp:button id="selBtn" onclick="View_Selected" runat="server"
name="selBtn" text="Show Selection"></asp:button>
The event handler of the button:
public void View_Selected(object sender, EventArgs e)
{
foreach( DataGridItem di in myDataGrid.Items )
{
HtmlInputCheckBox chkBx = (HtmlInputCheckBox)di.FindControl("EmpId") ;
if( chkBx !=null && chkBx.Checked )
{
Label lbl = (Label)di.FindControl("Id");
Response.Write( lbl.Text +"<br>" );
}
}
}
We loop through each DataGridItem
contained within the DataGrid
and search for the HtmlInputCheckBox
control and then check its value. If it is checked, we search for the Label
control in the DataGridItem
to get the �ID� field. Once we get the ID, we write it to the Response
.