本文為教程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" />
<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"按鈕后的情形。
用客戶端代碼實現"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);" />
<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函數。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
