首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

GridView 巢狀 CheckBoxList 互動實作:省市聯動全選邏輯

     編輯:ASP.NET 基礎

需求情境

在 GridView 每一列顯示一個省份,並內嵌 CheckBoxList 列出該省份下的所有城市。使用者勾選省份 CheckBox 時,自動全選/取消該列城市;頁面頂部「全選」再遞迴控制所有省份與城市。

前端 JavaScript 互動邏輯

關鍵在於 **動態 ClientID 規律推導**。GridView 命名容器產生的 ID 格式為:
ctl00_ContentPlaceHolder1_gvItem_ctl{rowIndex}_CheckBox1
ctl00_ContentPlaceHolder1_gvItem_ctl{rowIndex}_gvInnerItem (內層 CheckBoxList)

<script type="text/javascript">
var gvPrefix = "ctl00_ContentPlaceHolder1_gvItem_";

function getRowId(rowIndex) {
    // GridView 行索引從 0 起,ctl 編號從 2 起 (含 Header)
    var n = rowIndex + 2;
    return n < 10 ? "ctl0" + n : "ctl" + n;
}

// 省份 CheckBox 點擊 → 控制該列城市
function ProvinceClick(chk, rowIndex) {
    var rowId = getRowId(rowIndex);
    var cityListId = gvPrefix + rowId + "_gvInnerItem";
    var cityInputs = document.getElementById(cityListId).getElementsByTagName("input");
    for (var i = 0; i < cityInputs.length; i++)
        cityInputs[i].checked = chk.checked;
}

// 全選/取消
function SelectAll(chkAll) {
    var gv = document.getElementById(gvPrefix.replace("_gvItem_", "")); // 取得 GridView table
    var provinceChecks = gv.getElementsByTagName("input");
    for (var i = 0; i < provinceChecks.length; i++) {
        var id = provinceChecks[i].id;
        if (id.endsWith("_CheckBox1")) { // 省份 CheckBox
            provinceChecks[i].checked = chkAll.checked;
            // 觸發城市聯動
            var rowIdx = parseInt(id.match(/ctl(\d+)_/)[1]) - 2;
            if (rowIdx >= 0) ProvinceClick(provinceChecks[i], rowIdx);
        }
    }
}
</script>

ASPX 標記結構

<asp:GridView ID="gvItem" runat="server" AutoGenerateColumns="false"
    OnRowDataBound="gvItem_RowDataBound" DataKeyNames="State">
    <Columns>
        <asp:TemplateField HeaderText="選擇省份">
            <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server"
                    onclick='ProvinceClick(this, <%# Container.DataItemIndex %>)' />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="State" HeaderText="省份名稱" />
        <asp:TemplateField HeaderText="選擇城市">
            <ItemTemplate>
                <asp:CheckBoxList ID="gvInnerItem" runat="server"
                    RepeatLayout="Flow" RepeatDirection="Horizontal" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

<asp:CheckBox ID="chkAll" runat="server" Text="全選" onclick="SelectAll(this)" />

後端資料繫結

protected void gvItem_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var cbl = (CheckBoxList)e.Row.FindControl("gvInnerItem");
        string state = gvItem.DataKeys[e.Row.RowIndex].Value.ToString();
        string sql = $"SELECT DISTINCT City FROM CityTable WHERE State = '{state}'";
        DataTable dt = DbHelper.GetDataTable(sql); // 自行實作

        cbl.DataSource = dt;
        cbl.DataTextField = "City";
        cbl.DataValueField = "City";
        cbl.DataBind();
    }
}

取得使用者最終勾選結果

protected void btnSubmit_Click(object sender, EventArgs e)
{
    var selected = new List<string>();
    foreach (GridViewRow row in gvItem.Rows)
    {
        var cbl = (CheckBoxList)row.FindControl("gvInnerItem");
        foreach (ListItem item in cbl.Items)
        {
            if (item.Selected)
                selected.Add($"{gvItem.DataKeys[row.RowIndex].Value}-{item.Value}");
        }
    }
    // selected 即為 "省份-城市" 清單
}

注意事項

  • ClientID 模式:若設定 ClientIDMode="Static" 或 Predictable,JS 選取器需相應調整。
  • UpdatePanel 部分更新:若 GridView 在 UpdatePanel 內,非同步回發後需重新綁定 JS 事件 (使用 Sys.Application.add_load 或 PageRequestManager)。
  • 效能:城市資料量大時,考慮改用 AJAX 按需載入 (點擊省份才載入城市),避免首次渲染過大 HTML。

結語

GridView 巢狀 CheckBoxList 透過 **命名容器 ID 規律 + JavaScript 聯動**,能以極低成本實現階層式勾選介面。掌握 Container.DataItemIndex 傳遞行索引、FindControl 取得內層控制項、DataKeys 保留主鍵,是 WebForms 開發的核心技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved