GridView 將伺服器控件 (如 CheckBox) 轉譯為 HTML 時,會產生唯一 `ClientID` (如 `gvUserList_ctl02_ctl01`),導致 JavaScript 難以用固定 ID 操作。解決方案:使用**原生 HTML ``**,ASP.NET 不會修改其 `id`/`name` 屬性。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="MultiSelectGridView.aspx.cs" Inherits="MultiSelectGridView" %>
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
<title>GridView 全選/反選/批量刪除範例</title>
<script type="text/javascript">
// 取得同名 checkbox 集合
function getCheckboxes() {
return document.getElementsByName("CheckboxGroup");
}
// 全選
function SelectAll() {
var cbs = getCheckboxes();
for (var i = 0; i < cbs.length; i++) cbs[i].checked = true;
}
// 反選
function ReverseSelect() {
var cbs = getCheckboxes();
for (var i = 0; i < cbs.length; i++) cbs[i].checked = !cbs[i].checked;
}
// 檢查是否至少選一項
function CheckHasSelectedItem() {
var cbs = getCheckboxes();
for (var i = 0; i < cbs.length; i++) if (cbs[i].checked) return true;
return false;
}
// 刪除確認
function ConfirmDelete() {
if (CheckHasSelectedItem()) return confirm("確認刪除選中的使用者?");
alert("請至少選擇一項!"); return false;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="gvUserList" runat="server" AutoGenerateColumns="False" Width="800px"
AllowPaging="True" OnPageIndexChanging="gvUserList_PageIndexChanging" PageSize="5">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<input name="CheckboxGroup" type="checkbox" value='<%# Eval("UserId") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="UserId" HeaderText="編號" />
<asp:HyperLinkField DataNavigateUrlFields="UserId" DataNavigateUrlFormatString="ShowUser.aspx?UserId={0}"
DataTextField="RealName" HeaderText="查看" />
<asp:BoundField DataField="UserName" HeaderText="使用者名稱" />
<asp:BoundField DataField="RealName" HeaderText="真實姓名" />
<asp:BoundField DataField="Age" HeaderText="年齡" />
<asp:CheckBoxField DataField="Sex" HeaderText="性別" />
<asp:BoundField DataField="Mobile" HeaderText="手機" />
<asp:TemplateField HeaderText="電子郵件">
<ItemTemplate><%# Eval("Email") %></ItemTemplate>
<AlternatingItemTemplate>
<a href='mailto:<%# Eval("Email") %>'>寄信給 <%# Eval("RealName") %></a>
</AlternatingItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>目前沒有任何記錄。</EmptyDataTemplate>
</asp:GridView>
<table width="800" cellpadding="0" cellspacing="0" border="0">
<tr>
<td><a href="#" onclick="SelectAll(); return false;">全選</a></td>
<td><a href="#" onclick="ReverseSelect(); return false;">反選</a></td>
<td>
<asp:Button ID="btnDelete" runat="server" Text="刪除"
OnClientClick="return ConfirmDelete();" OnClick="btnDelete_Click" />
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
protected void btnDelete_Click(object sender, EventArgs e)
{
string ids = Request.Form["CheckboxGroup"]; // 格式: "15,16,17"
if (!string.IsNullOrEmpty(ids))
{
// 直接用 IN 查詢,無需拆分字串
string sql = "DELETE FROM Users WHERE UserId IN (" + ids + ")";
DbHelper.ExecuteNonQuery(sql);
gvUserList.DataBind(); // 重新繫結
}
}
<asp:HiddenField ID="hfSelectedIds" runat="server" />
// JS: 勾選時更新 HiddenField
function updateSelection(cb) {
var hf = document.getElementById('<%= hfSelectedIds.ClientID %>');
var ids = hf.value.split(',').filter(x => x);
var val = cb.value;
if (cb.checked) { if (!ids.includes(val)) ids.push(val); }
else { ids = ids.filter(x => x !== val); }
hf.value = ids.join(',');
}
// 後台刪除時讀取 hfSelectedIds.Value
使用原生 HTML checkbox 搭配同名分組,配合 `Request.Form` 取得逗號分隔 ID 字串,是 GridView 批量操作最簡潔高效的模式。搭配 JavaScript 全選/反選/確認對話框,提供完整的使用者操作體驗。