在GridView控件里全选CheckBox

系统 1447 0

本文为教程52的扩展阅读
英文原版及代码下载:
http://aspnet.4guysfromrolla.com/articles/052406-1.aspx

在GridView控件里全选CheckBox


导言:


通常的网站用户界面模式是这样的,每一行记录对应一个checkbox,典型的例子便是基于web的email客户端程序。通过点击checkbox来选择邮件,当一个或几个邮件时,用户可进行相同的操作,比如删除、阅读或者将它们转移的不同的文件夹,除了每个邮件对应的checkbox外,很多界面还包含一个"check all"的checkbox。如果选择或弃选该checkbox,系统将自动的全选或弃选下面所有的项。

ASP.NET 2.0的GridView控件—本文的焦点,可以用来创建这种用户界面。特别的,我们考察如何同时在服务器端和客户端实现“全选/弃选”(Check All/Uncheck All)功能。服务器端需要用户做出选择,页面产生回传后才能执行;另一方面,客户端需要稍微多做些工作才可以正确执行。


构建功能:创建一个GridView控件,每行对应一个CheckBox


现在让我们创建一个GridView控件,每行记录包含一个CheckBox,可以通过如下2种方法创建一列CheckBoxes:

.使用CheckBoxField—作为GridView控件内置的field类型,其呈现为一列CheckBox,每个CheckBox的Checked属性可以绑定到某个数据源的数据域(data field)

.使用一个TemplateField—我们可以添加一个TemplateField,然后在其ItemTemplate模板里面添加一个CheckBox控件。如果要对其Checked属性实施绑定的话,要么通过声明代码的方式(比如, <asp:CheckBox runat="server" ... Checked='<%# Eval("ColumnName") %>' ... />);要么通过编程的方式(比如在RowDataBound事件处理器).


第2种方法—使用一个TemplateField,相对而言具有一些优势。首先,可以更方便地进行用户定制。用最少的步骤我们就可以为每一行(each row)添加额外的代码,甚至提供一个自定义表头。在本文结束部分有一个代码下载链接,在其代码里包含了这种情况。更多的信息请参阅文章《 Checking All CheckBoxes in a GridView Using Client-Side Script and a Check All CheckBox》。此外,如果CheckBox的Checked属性未绑定到某个数据域,我们就需要使用TemplateField option,在本文我们将这样做。


在本文,假设我们需要创建一个基于web的文件管理工具,列出当前目录的文件。在GridView控件下面,我们添加一个"Delete All Checked Files"按钮。当点击时,将对应的CheckBox处于选中状态的那些文件删除掉。(本文结束时演示的例子并不会真的删除这些文件,而是显示一个消息提示哪些文章将被删除)


下面的GridView控件提供了我们需要的功能。注意到其使用了一个TemplateField为每一行记录设置一个CheckBox,(为求简化,我们将GridView控件的某些格式化设置删除了)

<asp:GridView ID="FileList" runat="server"
AutoGenerateColumns="False" DataKeyNames="FullName">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox runat="server" ID="RowLevelCheckBox" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="CreationTime" HeaderText="Created On">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="Length" DataFormatString="{0:N0}"
HeaderText="File Size"
HtmlEncode="False">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
</Columns>
</asp:GridView>


在Page_Load事件处理器里我们将当前目录里的文件绑定到GridView控件,代码如下:

Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim dirInfo As New DirectoryInfo(Request.PhysicalApplicationPath)

FileList.DataSource = dirInfo.GetFiles()
FileList.DataBind()
End If
End Sub


关于访问并展示某个目录下文件的更多信息,请参阅文章《Displaying the Files in a Directory using a DataGrid》


接下来,我们需要添加一个"Delete All Checked Files" 按钮。点击后,判断点击了哪些
CheckBoxes,并删除这些文件。以下为该按钮的Click事件处理器。通过GridView的Rows集,对每个GridViewRow实例,检查名为RowLevelCheckBox的CheckBox是否被选中,如果是,事件处理器将对应的文件路径显示在一个Label控件里。(在实际运用时,将用System.IO命名空间里的File.Delete(path)方法来删除文件)

Protected Sub DeleteButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DeleteButton.Click
Summary.Text = "The following file would have been deleted:<ul>"

Dim currentRowsFilePath As String

'Enumerate the GridViewRows
For index As Integer = 0 To FileList.Rows.Count - 1
'Programmatically access the CheckBox from the TemplateField
Dim cb As CheckBox = CType(FileList.Rows(index).FindControl("RowLevelCheckBox"), CheckBox)

'If it's checked, delete it...
If cb.Checked Then
currentRowsFilePath = FileList.DataKeys(index).Value
Summary.Text &= String.Concat("<li>", currentRowsFilePath, "</li>")
End If
Next

Summary.Text &= "</ul>"
End Sub


请注意我们是怎样通过编程来引用TemplateField模板里的CheckBox控件——FileList.Rows(index).FindControl("controlID").假如在这里我们使用的是CheckBoxField,上述代码里我们将替换为FileList.Rows(index).Cells(0).Controls(0).在这里,Cells(0)意为指定行记录的第一列(假设CheckBoxField是GridView控件的第一列);Control(0)意为Controls集里的第一个控件,对CheckBoxField来说,就是其CheckBox控件


现在我们构建了基本框架,接下来我们将添加全选或弃选GridView控件里所有CheckBox的功能。首先让我们看如何添加服务器端代码。


用服务器端代码实现"Check All"和"Uncheck All" 功能


为添加"Check All"和"Uncheck All" 功能,在GridView控件上面添加一个Button控件:

<p>
<asp:Button ID="CheckAll" runat="server" Text="Check All" />
&nbsp;
<asp:Button ID="UncheckAll" runat="server" Text="Uncheck All" />
</p>


接下来,我们为这些按钮创建Click事件处理器.我列举了GridView的Rows集,对每个GridViewRow实例,访问CheckBox并设置其Checked属性:

Protected Sub CheckAll_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles CheckAll.Click
'Enumerate each GridViewRow
For Each gvr As GridViewRow In FileList.Rows
'Programmatically access the CheckBox from the TemplateField
Dim cb As CheckBox = CType(gvr.FindControl("RowLevelCheckBox"), CheckBox)

'Check it!
cb.Checked = True
Next
End Sub

Protected Sub UncheckAll_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles UncheckAll.Click
'Enumerate each GridViewRow
For Each gvr As GridViewRow In FileList.Rows
'Programmatically access the CheckBox from the TemplateField
Dim cb As CheckBox = CType(gvr.FindControl("RowLevelCheckBox"), CheckBox)

'Uncheck it!
cb.Checked = False
Next
End Sub


以上就是所有我们需要做的. 服务器端方法的唯一问题是点击"Check All"或 "Uncheck All" 按钮后产生页面回传,导致屏幕刷新闪烁. 这种情况在企业内部局域网表现不明显,
而互联网站通过使用客户端脚本以提供更好的用户体验。我们要再多做些工作实现此功能。在我们将注意力转到客户端脚本前,花一些时间测试我们的服务器端方法。注意到,点击"Check All" 或 "Uncheck All" 按钮时,将相应的全选或弃选GridView的所有的CheckBox;下面的界面为点击 "Check All"按钮后的情形。

在GridView控件里全选CheckBox

用客户端代码实现"Check All"和"Uncheck All" 功能


为了提供更爽的用户体验,最理想的是在不产生页面回传的情况下,在客户端通过点击
"Check All" 或"Uncheck All"来实现全选或弃选的目的。可以通过客户端JavaScript来访问GridView控件里的那些CheckBox,用如下的模式:

// Get a reference to the CheckBox
var cb = document.getElementById('checkBoxID');

// Adjust the checked state
cb.Checked = false; // or whatever...

这里,checkBoxID是CheckBox控件的客户端ID(client-side ID),它不必与该控件的ID属性值相同。实际上客户端ID由该CheckBox控件的那些父控件(parent controls)的ID值构成。为了在客户端脚本处理这些CheckBox,我们需要创建一个客户端数组,以包含这些客户端ID。


ASP.NET 2.0的 ClientScriptManager class类里包含了一系列方法。这些方法可以直接通过ASP.NET页面的ClientScript属性来访问。在ASP.NET 1.x的Page class类里也可以找到这些与客户端脚本相关(client-script-related )的方法。在这些1.x和2.0共有的方法中,其中一个方法是RegisterArrayDeclaration(arrayName, arrayValue),它创建一个客户端数组,数组元素由输入参数arrayValue指定。

下面的代码列举了GridView的Rows集合,对每个GridViewRow实例,编程访问CheckBox并保存其客户端ID(通过在客户端数组里使用ClientID属性)

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim dirInfo As New DirectoryInfo(Request.PhysicalApplicationPath)

FileList.DataSource = dirInfo.GetFiles()
FileList.DataBind()
End If

'On every page visit we need to build up the CheckBoxIDs array
For Each gvr As GridViewRow In FileList.Rows
'Get a programmatic reference to the CheckBox control
Dim cb As CheckBox = CType(gvr.FindControl("RowLevelCheckBox"), CheckBox)

ClientScript.RegisterArrayDeclaration("CheckBoxIDs", String.Concat("'", cb.ClientID, "'"))
Next
End Sub


这将为页面添加JavaScript,看起来类似于这样:
<script type="text/javascript">
<!--
var CheckBoxIDs = new Array('<i>CheckBoxID1</i>','<i>CheckBoxID2</i>', ...,'<i>CheckBoxIDN</i>');
// -->
</script>


前面的代码应放置于Page_Load事件处理器,以便每次登录页面时执行代码,因为这种客户端注入类型的数组(types of client-side injected arrays)在页面发生回传后便失效
如果我们只是在首次登录页面(或任何GridView被绑定的时候)时创建客户端数组,一旦发生页面回传—比如点击"Delete All Checked Files"按钮后,再次登录页面时就不会包含这个名为CheckBoxIDs的客户端数组,因此“全选”或“弃选”功能就无从谈起。


关于客户端脚本和服务器端代码的更多信息,请参阅文章《Working with Client-Side Script》


用客户端ID对数组赋值后,我们来写一个客户端JavaScript函数,列举所有的数组元素,对每个元素,引用checkbox并设置其checked属性。为达此目的,我创建了2种方法:

.ChangeCheckBoxState(id, checkState):引用某个指定的checkbox (使用document.getElementById(id)),将其checked属性设置为checkedState的值

.ChangeAllCheckBoxStates(checkState):同样的,对数组CheckBoxIDs里的每个元素,调用ChangeCheckBoxState方法,传递客户端ID值和checkState值。


我创建了2个<input type="button" ... />的按钮—"Check All" 和 "Uncheck All" .设置它们的客户端onclick事件处理器调用ChangeAllCheckBoxStates方法,传递相应的checkState的值。

<script type="text/javascript">
function ChangeCheckBoxState(id, checkState)
{
var cb = document.getElementById(id);
if (cb != null)
cb.checked = checkState;
}

function ChangeAllCheckBoxStates(checkState)
{
// Toggles through all of the checkboxes defined in the CheckBoxIDs array
// and updates their value to the checkState input parameter
if (CheckBoxIDs != null)
{
for (var i = 0; i < CheckBoxIDs.length; i++)
ChangeCheckBoxState(CheckBoxIDs[i], checkState);
}
}
</script>

...

<p>
<input type="button" value="Check All" onclick="ChangeAllCheckBoxStates(true);" />
&nbsp;
<input type="button" value="Uncheck All" onclick="ChangeAllCheckBoxStates(false);" />
</p>


完成上述修改后,"Check All" 和 "Uncheck All" 按钮就可以在客户端完成相应的功能,并提供更友好的用户体验。在本文结尾部分下面,有一个实例代码下载链接。在实例里,checkbox列包含一个checkbox表头,选中或弃选该checkbox,就会相应的选中或弃选所有的checkbox。可以在文章《 Checking All CheckBoxes in a GridView Using Client-Side Script and a Check All CheckBox!》里找到另一个更彻底的例子。


结语:
在本文,我们探讨了2种方法来全选或弃选GridView控件里所有CheckBox。使用服务器端代码的方法要容易一些,不过要在页面回传后才能工作;而客户端方法可以提供更友好的用户体验,不过要多写些代码和JavaScript函数。

在GridView控件里全选CheckBox


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论