復合控制項封裝多個子控制項,外部無法直接存取子控制項(破壞封裝性)。因此,子控制項的事件(如 Button.Click、TextBox.TextChanged)必須「向上傳遞」為復合控制項的頂層事件,外部才能訂閱處理。這稱為事件上傳。
核心概念: 在 CreateChildControls 中為子控制項掛上事件處理常式,該處理常式內再呼叫復合控制項的頂層事件引發方法(OnEventName)。
public event EventHandler Submit;protected virtual void OnSubmit(EventArgs e) { if (Submit != null) Submit(this, e); }CreateChildControls 為子控制項掛接事件:btn.Click += new EventHandler(btn_Click);void btn_Click(object s, EventArgs e) { OnSubmit(EventArgs.Empty); }[ToolboxData("<{0}:SearchBox runat=server></{0}:SearchBox>")]
public class SearchBox : CompositeControl
{
private TextBox txtKeyword;
private Button btnSearch;
public event EventHandler Search;
protected virtual void OnSearch(EventArgs e)
{
if (Search != null) Search(this, e);
}
public string Keyword
{
get { EnsureChildControls(); return txtKeyword.Text; }
}
protected override void CreateChildControls()
{
txtKeyword = new TextBox { ID = "txtKeyword" };
btnSearch = new Button { ID = "btnSearch", Text = "搜尋" };
btnSearch.Click += new EventHandler(btnSearch_Click);
Controls.Add(txtKeyword);
Controls.Add(btnSearch);
}
void btnSearch_Click(object sender, EventArgs e)
{
OnSearch(EventArgs.Empty);
}
}
<cc:SearchBox ID="searchBox" runat="server" OnSearch="searchBox_Search" />
protected void searchBox_Search(object sender, EventArgs e)
{
string kw = searchBox.Keyword;
// 執行搜尋邏輯
}
核心概念: 利用 ASP.NET 控制項樹的 OnBubbleEvent 機制,子控制項引發事件時自動向上冒泡,父控制項覆寫 OnBubbleEvent 攔截並轉發為頂層事件。
RaiseBubbleEvent(this, e)(Button、LinkButton 等內建控制項已自動處理)。protected override bool OnBubbleEvent(object source, EventArgs e)。true 表示已處理。protected override bool OnBubbleEvent(object source, EventArgs e)
{
if (source == btnSearch && e is CommandEventArgs)
{
OnSearch(EventArgs.Empty);
return true;
}
return base.OnBubbleEvent(source, e);
}
此時 CreateChildControls 就不需手動掛接 btnSearch.Click,Button 的 Command 事件會自動冒泡。
| 維度 | 包含法 | 冒泡法 |
|---|---|---|
| 實作複雜度 | 直觀、程式碼較多 | 精簡、需理解冒泡機制 |
| 封裝性 | 父控制項明確掛接子事件 | 子控制項自主冒泡,父控制項被動接收 |
| 適用子控制項 | 任何支援事件的控制項 | 需支援 RaiseBubbleEvent(WebControl 內建) |
| 多層嵌套 | 需逐層手動轉發 | 自動穿透多層控制項樹 |
| 效能 | 略優(直接呼叫) | 極微小差異,可忽略 |
建議: 簡單復合控制項用包含法,易讀易維護;複雜、多層嵌套或需支援命令型事件(Command、RowCommand)時採用冒泡法。
若頂層事件需傳遞資料(如搜尋關鍵字),定義繼承 EventArgs 的類別:
public class SearchEventArgs : EventArgs
{
public string Keyword { get; private set; }
public SearchEventArgs(string keyword) { Keyword = keyword; }
}
public event EventHandler Search;
protected virtual void OnSearch(SearchEventArgs e)
{
if (Search != null) Search(this, e);
}
void btnSearch_Click(object sender, EventArgs e)
{
OnSearch(new SearchEventArgs(txtKeyword.Text));
}
[Category("Action")]、[Description("搜尋按鈕點擊時引發")] 屬性,讓屬性視窗顯示事件分類與說明。ICompositeControlDesignerAccessor 讓設計器正確重建子控制項。掌握「包含法」與「冒泡法」兩大事件上傳模式,即可輕鬆打造功能完整、封裝良好的 ASP.NET 2.0 復合控制項。依專案複雜度選擇適合模式,並善用自訂事件引數豐富事件資訊,讓使用者像操作原生控制項一樣自然。