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

ASP.NET 遞迴遍歷頁面控制項樹:通用清空 TextBox 與尋找指定型別控制項的最佳實踐

     編輯:ASP.NET 基礎

痛點:Controls 集合只包含直接子系

Page.Controls、Panel.Controls 等集合僅包含第一層子控制項。巢狀結構(GridView → Rows → Cells → TextBox、UserControl 內部控制項)若不遞迴,根本找不到深層節點。

方案一:非遞迴(僅適用扁平結構)

// 僅能處理 Page 直屬或單層容器內的 TextBox
for (int i = 0; i < this.Controls.Count; i++) {
    foreach (Control ctrl in Page.Controls[i].Controls) {
        if (ctrl is TextBox txt) txt.Text = string.Empty;
    }
}

⚠️ 缺陷:無法處理 FormView、Repeater、GridView、UserControl 等命名容器內的控制項。

方案二:標準遞迴遍歷(推薦基礎版)

/// 
/// 遞迴遍歷控制項樹,對所有 TextBox 執行動作
/// 
public void ClearAllTextBoxes(ControlCollection controls) {
    foreach (Control ctrl in controls) {
        if (ctrl is TextBox txt) {
            txt.Text = string.Empty;
        }
        if (ctrl.HasControls()) {
            ClearAllTextBoxes(ctrl.Controls); // 遞迴進入子樹
        }
    }
}

// 呼叫入口
protected void Page_Load(object sender, EventArgs e) {
    if (!IsPostBack) ClearAllTextBoxes(Page.Controls);
}

方案三:泛型委派版(通用尋找/處理任意型別)

/// 
/// 通用遞迴遍歷:尋找符合條件的控制項並執行動作
/// 
/// 目標控制項型別
/// 起始控制項集合
/// 對每個符合項執行的委派
/// 可選的額外過濾條件
public void ForEachControl(ControlCollection controls, Action action, Func predicate = null) 
    where T : Control {
    foreach (Control ctrl in controls) {
        if (ctrl is T target && (predicate == null || predicate(target))) {
            action(target);
        }
        if (ctrl.HasControls()) {
            ForEachControl(ctrl.Controls, action, predicate);
        }
    }
}

// 使用範例:清空所有 TextBox
ForEachControl(Page.Controls, txt => txt.Text = string.Empty);

// 使用範例:只清空 ID 以 "txtSearch" 開頭的 TextBox
ForEachControl(Page.Controls, 
    txt => txt.Text = string.Empty, 
    txt => txt.ID.StartsWith("txtSearch"));

// 使用範例:收集所有 DropDownList 並重新繫結
var dropdowns = new List();
ForEachControl(Page.Controls, ddl => dropdowns.Add(ddl));
foreach (var ddl in dropdowns) RebindDropdown(ddl);

進階議題:命名容器與 FindControl

ASP.NET 控制項實作 INamingContainer(GridView、Repeater、FormView、UserControl)會建立獨立的 NamingContainer 作用域。遞迴遍歷 Controls 集合天然穿透命名容器,無需額外處理,這比 Page.FindControl("id") 更強大,因為:

  • 不需要知道完整的 ClientID(含 ctl00$ContentPlaceHolder1$... 前綴)。
  • 可批次處理同型別控制項,而非單一 ID 查找。

效能與遞迴深度考量

  • 典型頁面控制項樹深度 < 20,遞迴堆疊安全。
  • 若頁面控制項超過 5,000 個(極罕見),建議改用迭代器 + 显式堆疊避免 StackOverflowException。
  • 頻繁呼叫時,可快取 List 扁平化結果,但需在 PreRender 後失效(動態控制項可能變更)。

總結:選對工具解決問題

需求推薦做法
單一已知 ID 查找Page.FindControl("id") 或 NamingContainer.FindControl("id")
批次處理同型別控制項(清空、驗證、繫結)泛型遞迴 ForEachControl
需依條件篩選(ID 前綴、CSS Class、自訂屬性)泛型遞迴 + predicate
動態新增控制項後立即操作在 PreRender 階段遍歷,確保控制項樹已建構完成

掌握遞迴遍歷控制項樹,是 ASP.NET Web Forms 開發者處理複雜頁面交互的基本功,亦是理解控制項樹架構的最佳切入點。

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