許多開發者知道要重寫 Render 方法,卻不清楚為什麼不重寫 RenderControl 或 RenderChildren。本文透過原始碼邏輯與頁面追蹤實驗,徹底釐清三者關係。
// RenderControl:進入點,檢查 Visible
public void RenderControl(HtmlTextWriter writer)
{
if (Visible) Render(writer);
}
// Render:預設委派給 RenderChildren
protected virtual void Render(HtmlTextWriter writer)
{
RenderChildren(writer);
}
// RenderChildren:遞迴渲染所有子控件
protected virtual void RenderChildren(HtmlTextWriter writer)
{
foreach (Control c in Controls)
c.RenderControl(writer);
}
RenderControl。RenderControl 檢查 Visible,通過則呼叫 Render。Render 預設呼叫 RenderChildren。RenderChildren 遍歷 Controls 集合,對每個子控件呼叫 RenderControl → 形成遞迴。在頁面放置三個 Panel,將按鈕的 Visible=false,啟用 Trace 後可見:

| 方法 | 適用場景 |
|---|---|
| Render | 最常見:輸出自訂 HTML、包裝子控件渲染 |
| RenderContents | 繼承 WebControl 時,僅輸出內部內容 |
| RenderChildren | 極少見:需完全接管子控件渲染順序/條件 |
| RenderControl | 幾乎不重寫:屬公開進入點,邏輯固定 |
理解這套遞迴機制,能讓你在複雜控件樹中精準控制輸出,避免重複渲染或遺漏子控件。