|
<p >最近,我在新闻组中看到许多关于建立类似Hotmail中,在DataGrid控件中带有CheckBox控件的讨论。这篇文章将帮助你解决这个问题。<p >首先的问题是必须在DataGrid控件中的每一项前面都增加一个CheckBox控件,并且在这一列CheckBox控件的顶部还有一个CheckBox控件。无论DataGrid控件中每一项前面的CheckBox控件是否选择,当选择或者不选择位于DataGrid控件顶部CheckBox控件的时候,DataGrid控件中的所有CheckBox控件都将随之被选择或者不选择。实际上,这些CheckBox控件的选择或者不选择都是客户端的脚本行为。因此,我们不得不编写服务器端代码来被客户端的脚本所控制。<p >另外一个问题是当点击一个外部的按钮时,我们应该能够在服务器端得到所有在DataGrid控件中被选择的项目。<p ><center><font color="#000099"><strong>带有CheckBox的DataGrid控件</strong></font></center><p >我们首先处理第一个问题,如何在DataGrid控件中每一项的前面都增加一个CheckBox控件以及在DataGrid控件的顶部增加一个CheckBox控件。为了直接的演示这个实例,我们将使用MS SQL Server中默认安装的Pubs数据库。具体的代码如下:<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code><%@ Import Namespace="System.Data" %><%@ Import Namespace="System.Data.SqlClient" %><html><script language="C#" runat="server">SqlConnection myConnection;protected void Page_Load(Object Src, EventArgs E){ myConnection = new SqlConnection("server=(local)\\NetSDK;database=pubs;Trusted_Connection=yes");if (!IsPostBack)BindGrid();}public void BindGrid(){SqlDataAdapter myCommand = new SqlDataAdapter("select * from Authors", myConnection); DataSet ds = new DataSet(); myCommand.Fill(ds, "Authors"); MyDataGrid.DataSource=ds.Tables["Authors"].DefaultView; MyDataGrid.DataBind();}</script><body style="font: 10pt verdana"><form runat="server" id="form1" name="form1" ><h3><font face="Verdana">Working with Checkboxes within a DataGrid</font></h3><ASP ataGrid id="MyDataGrid" runat="server"Width="800"BackColor="#ccccff"BorderColor="black" ShowFooter="false"CellPadding=3 CellSpacing="0" Font-Name="Verdana" Font-Size="8pt"HeaderStyle-BackColor="#aaaadd" AutoGenerateColumns="false" ><Columns><asp:TemplateColumn HeaderText="contract" ><HeaderTemplate><input type=checkbox id="checkAll" runat="server">Contracts </HeaderTemplate><ItemTemplate><input type=checkbox runat="server" id="contract"checked='<%# DataBinder.Eval(Container.DataItem, "contract") %>'/> </ItemTemplate></asp:TemplateColumn> <asp:BoundColumn HeaderText="au_id" DataField="au_id" /> <asp:BoundColumn HeaderText="au_lname"DataField="au_lname" /><asp:TemplateColumn HeaderText="au_fname" ><ItemTemplate> <asp abel id="au_fname" Text='<%# DataBinder.Eval(Container.DataItem, "au_fname") %>'runat="server" /></ItemTemplate> </asp:TemplateColumn><asp:BoundColumn HeaderText="city" DataField="city" /></Columns></ASP ataGrid></form></body></html></ccid_code></pre></td></tr></table></ccid_nobr><p >上面的代码应该很容易的被你所理解。我只是简单的将Pubs数据库中Authors表绑定到DataGrid控件上。<p >这里唯一需要进行解释的是在DataGrid控件中定义了一个自定义的模板。因为我需要将字段Contract用CheckBox控件的选择或者不选择的方式显示出来,我使用了一个自定义的TemplateColumn模板,将数据库中Boolean类型的字段Contract通过HtmlInputCheckBox控件的checked属性表现出来。为此,在TemplateColumn模板中,我还定义了一个HeaderItem模板,并且在里面放置了一个HtmlInputCheckBox控件。<p >这里值得注意的一点是如果你需要在服务器控件中执行任何客户端的脚本,HtmlControls(Html控件)是最简单的选择。因此,我使用HtmlInputCheckBox控件并且在ItemTemplate中将字段au_fname中的数据与其绑定,并且在下面的小节中我还需要取得这个字段的返回值。<p >下面,我更改了位于DataGrid控件顶部的HtmlInputCheckBox控件的定义,让它的onclick客户端事件调用一个JavaScript函数CheckAll()。这个更改的代码如下:<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code><input type=checkbox id="checkAll" onclick="CheckAll(this);" runat="server"></ccid_code></pre></td></tr></table></ccid_nobr><p >现在,将有很多种方法来处理这种通过JavaScript脚本的交互,我的目标是建立一个通用的功能。当位于顶部的CheckBox控件选择或者不选择时,DataGrid控件中所有项目前面的CheckBox控件也将随之选择或者不选择。在代码的DataGrid定义中增加下面的代码:<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code><script >var frm = document.form1 ;function CheckAll( checkAllBox ){var actVar = checkAllBox.checked ;for(i=0;i< frm.length;i++) {e=frm.elements;if ( e.type=='checkbox' && e.name.indexOf("contract") != -1)e.checked= actVar ; }}</script></ccid_code></pre></td></tr></table></ccid_nobr><p >在上面的JavaScript代码中,我首先检查了位于顶部的CheckBox的状态。然后,我通过循环来查找在form中,所有元素的名字包中含关键字"contract"的CheckBox控件。值得注意的是,在ASP.NET页面被运行时,会为客户端页面的每一个控件都分配一个固定的名字。因此我使用indexof函数来匹配我需要选择的CheckBox控件的名字。最后,我设置这些CheckBox控件的值与位于顶部的CheckBox控件的状态相一致。<p >这段代码可以正常的被执行,但这里有一个小小的错误。当位于顶部的CheckBox控件被选择的时候,DataGrid控件中所有项目前面的CheckBox也将随着被选择。但如果DataGrid控件中的CheckBox控件在其后有任何一个不被选择,位于顶部的CheckBox控件依然处于被选择的状态中,这就是错误的。<p >理想的情况时,如果在DataGrid控件中所有项目前面的CheckBox都被选择的时候,位于顶部的CheckBox控件才被选择。否则,只要在DataGrid控件中的CheckBox控件有一个没有被选择,位于顶部的CheckBox控件都将处于不选择的状态。<p >为了实现这样的功能,我们需要为DataGrid控件中所有项目前面的CheckBox控件添加另外一个JavaScript函数,定义的代码如下:<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code><input type=checkbox runat="server" id="contract" onclick="UnCheck();" checked='<%# DataBinder.Eval(Container.DataItem, "contract") %>'/></ccid_code></pre></td></tr></table></ccid_nobr><p >并且添加新的JavaScript函数如下:<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code>function UnCheck(){for(i=0;i< frm.length;i++){e=frm.elements; if ( e.type=='checkbox' && e.name.indexOf("checkAll") != -1 ){e.checked= false ;break;}}}</ccid_code></pre></td></tr></table></ccid_nobr><p >在上面的代码片断中,我通过查找form中所有元素来找到位于顶部的CheckBox控件并且将它设置为不选择的状态。<p >现在已经完成了第一个需求。你可以保存它并且测试这个页面了。<p ><center><font color="#000099"><strong>列出所有的选中项目</strong></font></center><p >在这一部分中,我将讨论如何得到有关被选择的CheckBox控件的返回情况。在服务器端,一旦我们知道了哪一个CheckBox控件被选择,我们就可以对它们执行相应的操作,通常是删除或者选择。<p >首先,我们按照下面的方法在页面中添加一个Button控件。<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code><asp:button Text="List Selected" runat="server" OnClick="Show_Selected" /></ccid_code></pre></td></tr></table></ccid_nobr><p >然后,按照下面的代码,定义它的事件。<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code>public void Show_Selected( object sender, EventArgs e){foreach( DataGridItem di in MyDataGrid.Items ){HtmlInputCheckBox cb = (HtmlInputCheckBox)di.FindControl("contract") ;if( cb !=null && cb.Checked ){Label lb = (Label)di.FindControl("au_fname"); Response.Write( lb.Text +"<br>" );}}}</ccid_code></pre></td></tr></table></ccid_nobr><p >在上面的方法中,我依然通过循环来查找在DataGrid控件中的每个项目(DataGridItem),找到需要的HtmlInputCheckBox控件。然后检查它们的值,最后被选中项目的第一列(即au_fname字段的值)将通过使用Response.Write方法显示在屏幕上。你还可以对这些选中的项目执行其他的操作。但有两点我将在这里指出:<p >1) 我显示的是au_fname字段的值,如果你记得在第一部分中我为这个字段定义的ItemTemplate,你也可以使用DataGridItem的ControlCollection indexer来找到并且得到返回值。<p >2) 如果在你的DataGrid控件中使用分页显示,上面的方法将不会正常的工作。在那样的情况中,你不得不检查页面数量(PageSize)和当前页面(CurrentPage)中DataGrid的属性,然后从显示出来的项目中得到返回值。<p >下面我列出了这篇文章所有的代码。<p ><ccid_nobr><table width="550" border="1" cellspacing="0" cellpadding="2" bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code><%@ Import Namespace="System.Data" %><%@ Import Namespace="System.Data.SqlClient" %><html><script language="C#" runat="server">SqlConnection myConnection;protected void Page_Load(Object Src, EventArgs E){myConnection = new SqlConnection("server=(local)\\NetSDK;database=pubs;Trusted_Connection=yes");if (!IsPostBack) BindGrid();}public void BindGrid(){SqlDataAdapter myCommand = new SqlDataAdapter("select * from Authors", myConnection);DataSet ds = new DataSet();myCommand.Fill(ds, "Authors"); MyDataGrid.DataSource=ds.Tables["Authors"].DefaultView; MyDataGrid.DataBind();}public void Show_Selected( object sender, EventArgs e){foreach( DataGridItem di in MyDataGrid.Items ){HtmlInputCheckBox cb = (HtmlInputCheckBox)di.FindControl("contract") ; if( cb !=null && cb.Checked ){Label lb = (Label)di.FindControl("au_fname"); Response.Write( lb.Text +"<br>" );}}}</script><body style="font: 10pt verdana"><form runat="server" id="form1" name="form1" ><h3><font face="Verdana">Working with Checkboxes within a DataGrid</font></h3><ASP ataGrid id="MyDataGrid" runat="server" Width="800" BackColor="#ccccff" BorderColor="black" ShowFooter="false" CellPadding=3 CellSpacing="0" Font-Name="Verdana" Font-Size="8pt" HeaderStyle-BackColor="#aaaadd" AutoGenerateColumns="false" ><Columns> <asp:TemplateColumn HeaderText="contract" ><HeaderTemplate><input type=checkbox id="checkAll" onclick="CheckAll(this);" runat="server"> Contracts</HeaderTemplate> <ItemTemplate><input type=checkbox runat="server" id="contract" onclick="UnCheck();"checked='<%# DataBinder.Eval(Container.DataItem, "contract") %>'/> </ItemTemplate> </asp:TemplateColumn> <asp:BoundColumn HeaderText="au_id" DataField="au_id" /> <asp:BoundColumn HeaderText="au_lname" DataField="au_lname" /> <asp:TemplateColumn HeaderText="au_fname" ><ItemTemplate> <asp abel id="au_fname"Text='<%# DataBinder.Eval(Container.DataItem, "au_fname") %>'runat="server" /> </ItemTemplate></asp:TemplateColumn> <asp:BoundColumn HeaderText="city" DataField="city" /></Columns></ASP ataGrid><br><asp:button Text="显示选中的项目" runat="server" OnClick="Show_Selected" /><script >var frm = document.form1 ;function CheckAll( checkAllBox ){var actVar = checkAllBox.checked ;for(i=0;i< frm.length;i++) {e=frm.elements;if ( e.type=='checkbox' && e.name.indexOf("contract") != -1 )e.checked= actVar ; }}function UnCheck(){for(i=0;i< frm.length;i++){e=frm.elements;if ( e.type=='checkbox' && e.name.indexOf("checkAll") != -1 ) { e.checked= false ;break;}}}</script></form></body></html></ccid_code></pre></td></tr></table></ccid_nobr><p ><center><font color="#000099"><strong>小结</strong></font></center><p >在这篇文章中,我们看到了如何使用客户端的JavaScript脚本与位于DataGrid控件中嵌套的CheckBox控件相交互。我希望这篇文章能够帮助你扩展更多关于DataGrid控件使用的想法。<p >(责任编辑:Sunny) <p align="center"></p></p> |
|