各位開發者朋友們,新年快樂!經過一段時間的沉澱,我們終於迎來第 16 篇。前 15 篇系統性地涵蓋了 ASP.NET 伺服器控件開發的核心知識體系。本篇將進行階段性總結,並深入探討模板控件進階主題,為後續資料綁定控件、複合控件開發奠定堅實基礎。
| 基類 | 適用場景 | 獲得功能 |
|---|---|---|
Control | 極簡控件、無 UI 樣式需求、效能極致要求 | 基本生命週期、視圖狀態、命名容器 |
WebControl | 標準 UI 控件、需樣式/屬性/無障礙支援 | Style、Attributes、ToolTip、TabIndex、AccessKey 等 |
CompositeControl (2.0+) | 複合控件、封裝多個子控件 | 自動實作 INamingContainer、CreateChildControls 流程 |
內建控件 (如 Button, GridView) | 需求與內建高度相似、僅需微調 | 完整現有功能、最小改動成本 |
Render(HtmlTextWriter):基礎渲染入口,輸出完整 HTML 標籤 (含開關標籤)RenderContents(HtmlTextWriter):僅輸出內容,外層標籤由 RenderBeginTag/RenderEndTag 處理RenderChildren(HtmlTextWriter):遞迴渲染子控件集合WebControl 覆寫 RenderContents;繼承 Control 覆寫 RenderIPostBackEventHandler 處理回發事件RaisePostBackEvent(string eventArgument) 為核心方法Page.GetPostBackEventReference(this, argument) 產生客戶端回發腳本eventArgument 區分
TypeConverter、DesignerSerializationVisibility.Content、PersistenceMode.InnerPropertyCollectionBase 或 List<T>,支援宣告式巢狀標籤[Category], [Description], [DefaultValue], [Browsable], [Editor] 等Style 基類封裝 CSS 樣式屬性TableItemStyle、PanelStyle 等專用衍生類CreateControlStyle()、ControlStyle、ApplyStyle() 核心方法IStateManager 自動持久化ViewState 屬性包 (頁面層級)IStateManager 介面:LoadViewState/SaveViewState/TrackViewStateSaveViewState()/LoadViewState() 覆寫TrackViewState()
public class DynamicTemplate : ITemplate
{
private readonly string _templateText;
public DynamicTemplate(string templateText)
{
_templateText = templateText;
}
public void InstantiateIn(Control container)
{
// 解析模板文字,動態建立控件樹
// 簡化示範:直接輸出 Literal
Literal lit = new Literal { Text = _templateText };
container.Controls.Add(lit);
}
}
// 使用方式
protected void Page_Load(object sender, EventArgs e)
{
MyTemplateControl1.ItemTemplate = new DynamicTemplate("動態生成: " + DateTime.Now + "");
}
public class CompiledTemplateBuilder
{
public static ITemplate BuildTemplate(string templateMarkup)
{
// 使用 BuildManager 編譯模板標記為型別
// 此為進階技術,生產環境建議使用預編譯模板
var page = new Page();
var control = page.ParseControl(templateMarkup);
return new ControlTemplate(control);
}
}
public class ControlTemplate : ITemplate
{
private readonly Control _templateControl;
public ControlTemplate(Control templateControl)
{
_templateControl = templateControl;
}
public void InstantiateIn(Control container)
{
// 複製控件樹 (需深度複製)
Control copy = CopyControlTree(_templateControl);
container.Controls.Add(copy);
}
private Control CopyControlTree(Control source)
{
// 實作控件樹深度複製邏輯
// 注意:需處理 ID、事件、視圖狀態等
return source; // 簡化
}
}
public class TemplateSelectorControl : WebControl, INamingContainer
{
// 多模板定義
public ITemplate DefaultTemplate { get; set; }
public ITemplate PremiumTemplate { get; set; }
public ITemplate AdminTemplate { get; set; }
public object DataSource { get; set; }
protected override void CreateChildControls()
{
Controls.Clear();
IEnumerable data = ResolveDataSource();
if (data != null)
{
foreach (object item in data)
{
// 根據資料項屬性選擇模板
ITemplate template = SelectTemplate(item);
DataBoundItem container = new DataBoundItem { DataItem = item };
template?.InstantiateIn(container);
container.DataBind();
Controls.Add(container);
}
}
ChildControlsCreated = true;
}
protected virtual ITemplate SelectTemplate(object dataItem)
{
// 範例:根據 User.Role 選擇模板
if (dataItem is User user)
{
switch (user.Role)
{
case "Admin": return AdminTemplate;
case "Premium": return PremiumTemplate;
default: return DefaultTemplate;
}
}
return DefaultTemplate;
}
}
Eval/Bind、設計時 IntelliSensePersistenceMode.InnerProperty + Browsable(false)INamingContainerEmptyDataTemplate、EmptyItemTemplateITemplateEditingFrame、TemplateEditingService控件開發是系統性工程,涵蓋繼承選擇、渲染管線、事件模型、屬性系統、樣式管理、視圖狀態、模板架構七大核心支柱。模板控件作為複雜控件的基石,掌握 ITemplate、InstantiateIn、IDataItemContainer 三大核心,配合動態模板、模板選擇器等進階技術,能構建出極具彈性與復用價值的 UI 元件庫。新的一年,讓我們繼續深入探索控件開發的奧秘!