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

ASP.NET Repeater 嵌套 Repeater 完整實現:主從數據綁定與 ItemDataBound 事件處理

     編輯:更多程式設計知識

在 ASP.NET WebForms 中,Repeater 控件不支援自動主從綁定,需手動在外層 ItemDataBound 事件中為內層 Repeater 指定數據源並綁定。本文提供完整的分類-產品兩級嵌套示例。

後端代碼

public partial class NestedRepeater : System.Web.UI.Page {
    private DataTable dtCategory;
    private DataTable dtProduct;

    protected void Page_Load(object sender, EventArgs e) {
        if (!IsPostBack) {
            dtCategory = GetCategoryTable();
            dtProduct  = GetProductTable();
            rptCategoryList.DataSource = dtCategory;
            rptCategoryList.DataBind();
        }
    }

    // 模擬分類表
    private DataTable GetCategoryTable() {
        var dt = new DataTable();
        dt.Columns.Add("CategoryId", typeof(int));
        dt.Columns.Add("CategoryTitle", typeof(string));
        for (int i = 1; i <= 3; i++) {
            dt.Rows.Add(i, "分類名字 " + i);
        }
        return dt;
    }

    // 模擬產品表
    private DataTable GetProductTable() {
        var dt = new DataTable();
        dt.Columns.Add("ProductTitle", typeof(string));
        dt.Columns.Add("CategoryId", typeof(int));
        for (int i = 1; i <= 9; i++) {
            int catId = i > 6 ? 3 : (i > 3 ? 2 : 1);
            dt.Rows.Add("產品名字 " + i, catId);
        }
        return dt;
    }

    // 根據分類 ID 篩選產品
    private DataTable GetProductTable(int categoryId) {
        var dv = dtProduct.DefaultView;
        dv.RowFilter = "CategoryId = " + categoryId;
        return dv.ToTable();
    }

    // 外層 Repeater 綁定時,為內層指定數據源
    protected void rptCategoryList_ItemDataBound(object sender, RepeaterItemEventArgs e) {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
            var drv = (DataRowView)e.Item.DataItem;
            var ltlTitle = (Literal)e.Item.FindControl("ltlTitle");
            ltlTitle.Text = drv["CategoryTitle"].ToString();

            var rptProductList = (Repeater)e.Item.FindControl("rptProductList");
            int catId = Convert.ToInt32(drv["CategoryId"]);
            rptProductList.DataSource = GetProductTable(catId);
            rptProductList.DataBind();
        }
    }

    // 內層 Repeater 綁定產品標題
    protected void rptProductList_ItemDataBound(object sender, RepeaterItemEventArgs e) {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
            var drv = (DataRowView)e.Item.DataItem;
            var ltlTitle = (Literal)e.Item.FindControl("ltlTitle");
            ltlTitle.Text = drv["ProductTitle"].ToString();
        }
    }
}

前端 ASPX 標記

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NestedRepeater.aspx.cs" Inherits="Demo.NestedRepeater" %>
<!DOCTYPE html>
<html>
<head runat="server">
    <title>Repeater 嵌套示例</title>
    <style>
        .listBox { margin-bottom: 20px; border: 1px solid #ddd; padding: 10px; }
        .title { font-weight: bold; font-size: 1.1em; color: #333; margin-bottom: 10px; }
        .content ul { list-style: none; padding-left: 20px; }
        .content li { margin: 5px 0; color: #666; }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Repeater ID="rptCategoryList" runat="server" OnItemDataBound="rptCategoryList_ItemDataBound">
                <ItemTemplate>
                    <div class="listBox">
                        <div class="title">
                            <asp:Literal ID="ltlTitle" runat="server" />
                        </div>
                        <div class="content">
                            <ul>
                                <asp:Repeater ID="rptProductList" runat="server" OnItemDataBound="rptProductList_ItemDataBound">
                                    <ItemTemplate>
                                        <li><asp:Literal ID="ltlTitle" runat="server" /></li>
                                    </ItemTemplate>
                                </asp:Repeater>
                            </ul>
                        </div>
                    </div>
                </ItemTemplate>
            </asp:Repeater>
        </div>
    </form>
</body>
</html>

關鍵技術點解析

  1. 數據準備分離:Page_Load 只準備主表與從表完整數據,不進行關聯。
  2. ItemDataBound 事件鏈:外層綁定每一行時,觸發事件 → 取得當前行 CategoryId → 篩選從表 → 綁定內層 Repeater。
  3. FindControl 獲取內層控件:e.Item.FindControl("rptProductList") 必須在 ItemTemplate 內查找。
  4. DataView.RowFilter 高效篩選:內存過濾避免重複查庫,適合中小數據量。

性能優化建議

  • 大數據量時,外層綁定前預先構建 Dictionary<int, DataTable> 分類產品映射,避免重複 RowFilter。
  • 考慮使用 ListView + GroupTemplate 替代雙重 Repeater,語義更清晰。
  • 啟用 ViewState 時注意體積,嵌套繁多可關閉內層 EnableViewState="false"。

常見錯誤

此模式適用於所有「一對多」層級展示:省市區、訂單明細、評論回覆等,掌握核心事件流即可舉一反三。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤原因修正
內層無數據未在外層 ItemDataBound 中綁定內層補全綁定邏輯
FindControl 返回 nullID 拼寫錯誤或控件不在命名容器內檢查 ID、確保在 ItemTemplate 內
數據錯亂使用全局變量未按行篩選每行根據 CategoryId 篩選