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

ASP.NET 2.0 復合控制項完整入門:概念、架構差異與建立實戰

     編輯:關於ASP.NET

什麼是復合控制項?

復合控制項 由多個現有控制項(子控制項)組合而成,對外暴露統一的屬性、方法、事件介面,封裝內部複雜度。經典例子:Login 控制項內含 Label、TextBox、Button、Validator,開發者只需設定幾個屬性即可擁有完整登入功能。

復合控制項 vs 使用者控制項

維度復合控制項使用者控制項 (.ascx)
建立方式C#/VB 程式碼(繼承 CompositeControl)宣告式標記 + 程式碼後置
部署單位組件 (.dll),可跨專案重用檔案 (.ascx),通常專案內部使用
設計時支援完整工具箱拖曳、屬性視窗、智慧標籤僅支援原始碼檢視拖曳,屬性視窗有限
版本控制組件版本、強名稱、GAC 部署隨專案原始碼版控
適用場景通用元件庫、商業控制項、跨專案共用專案專用 UI 區塊(頁首、選單、頁尾)

核心基類:CompositeControl

public abstract class CompositeControl : WebControl, INamingContainer, ICompositeControlDesignerAccessor
  • WebControl:提供樣式屬性(BackColor、ForeColor、Border...)。
  • INamingContainer:建立獨立命名容器,確保子控制項 ID 唯一(ctl00$MyComposite$txtName),支援資料繫結、事件路由、樣板。
  • ICompositeControlDesignerAccessor:讓設計器能在設計時重建子控制項(RecreateChildControls)。

建立復合控制項五大關鍵步驟

  1. 繼承 CompositeControl(或 CompositeDataBoundControl 針對資料繫結)。
  2. 覆寫 CreateChildControls:實例化子控制項、設定屬性、掛接事件、加入 Controls 集合。
  3. 呼叫 EnsureChildControls:在存取子控制項的屬性/方法前,確保子控制項已建立。
  4. 實作頂層屬性/事件:透過包含法或冒泡法暴露子控制項功能。
  5. (選擇性)實作設計時支援:自訂設計器、工具箱圖示、智慧標籤動作。

實戰範例:簡易登入表單復合控制項

1. 類別定義與子控制項建立

[ToolboxData("<{0}:SimpleLogin runat=server></{0}:SimpleLogin>")]
public class SimpleLogin : CompositeControl
{
    private TextBox _txtUser, _txtPwd;
    private Button _btnLogin;
    private Label _lblMsg;
    private RequiredFieldValidator _valUser, _valPwd;

    protected override void CreateChildControls()
    {
        Controls.Clear();

        _txtUser = new TextBox { ID = "txtUser" };
        _txtPwd = new TextBox { ID = "txtPwd", TextMode = TextMode.Password };
        _btnLogin = new Button { ID = "btnLogin", Text = "登入" };
        _lblMsg = new Label { ID = "lblMsg", ForeColor = Color.Red, Visible = false };
        _valUser = new RequiredFieldValidator { ID = "valUser", ControlToValidate = "txtUser", ErrorMessage = "請輸入帳號", Display = ValidatorDisplay.Dynamic };
        _valPwd = new RequiredFieldValidator { ID = "valPwd", ControlToValidate = "txtPwd", ErrorMessage = "請輸入密碼", Display = ValidatorDisplay.Dynamic };

        _btnLogin.Click += new EventHandler(btnLogin_Click);

        // 佈局:使用 Table 或 Panel 包裝
        Table layout = new Table();
        layout.Rows.Add(new TableRow { Cells = { new TableCell { Text = "帳號:" }, new TableCell { Controls = { _txtUser, _valUser } } } });
        layout.Rows.Add(new TableRow { Cells = { new TableCell { Text = "密碼:" }, new TableCell { Controls = { _txtPwd, _valPwd } } } });
        layout.Rows.Add(new TableRow { Cells = { new TableCell { ColumnSpan = 2, Controls = { _btnLogin } } } });
        layout.Rows.Add(new TableRow { Cells = { new TableCell { ColumnSpan = 2, Controls = { _lblMsg } } } });

        Controls.Add(layout);
    }

2. 頂層屬性與事件


    public string UserName { get { EnsureChildControls(); return _txtUser.Text; } }
    public string Password { get { EnsureChildControls(); return _txtPwd.Text; } }

    public event EventHandler LoginClick;
    protected virtual void OnLoginClick(EventArgs e) { if (LoginClick != null) LoginClick(this, e); }

    void btnLogin_Click(object sender, EventArgs e)
    {
        if (Page.IsValid) OnLoginClick(EventArgs.Empty);
    }

    public void ShowMessage(string msg, bool isError)
    {
        EnsureChildControls();
        _lblMsg.Text = msg;
        _lblMsg.ForeColor = isError ? Color.Red : Color.Green;
        _lblMsg.Visible = true;
    }
}

3. 網頁使用

<%@ Register Assembly="MyControls" Namespace="MyControls" TagPrefix="cc" %>
<cc:SimpleLogin ID="loginCtrl" runat="server" OnLoginClick="loginCtrl_LoginClick" />

protected void loginCtrl_LoginClick(object sender, EventArgs e)
{
    if (Membership.ValidateUser(loginCtrl.UserName, loginCtrl.Password))
    {
        FormsAuthentication.RedirectFromLoginPage(loginCtrl.UserName, false);
    }
    else
    {
        loginCtrl.ShowMessage("帳號或密碼錯誤", true);
    }
}

進階主題

樣板支援

定義 ITemplate 屬性(如 LayoutTemplate、LoggedInTemplate),在 CreateChildControls 中用 InstantiateIn 具現化,實現完全客製化外觀(參考 Login、ListView)。

資料繫結復合控制項

繼承 CompositeDataBoundControl,覆寫 CreateDataItem、DataBind,支援 DataSourceID、DataMember 等標準資料繫結模式。

設計時體驗強化

  • 自訂設計器繼承 CompositeControlDesigner,覆寫 GetDesignTimeHtml 提供設計時預覽。
  • 加入 [ToolboxBitmap(typeof(SimpleLogin), "SimpleLogin.bmp")] 設定工具箱圖示。
  • 實作 ICompositeControlDesignerAccessor.RecreateChildControls 讓屬性變更即時生效。

常見陷阱與解決方案

問題原因解決
子控制項事件不觸發未在 CreateChildControls 掛接事件、或未呼叫 EnsureChildControls確保事件掛接在 CreateChildControls,屬性存取前呼叫 EnsureChildControls
ViewState 遺失子控制項未正確加入 Controls 集合、或 ID 重複INamingContainer 確保唯一 ID,子控制項必須加入 Controls
設計時錯誤「創建控制項時出錯」標記語法錯誤、缺少 runat="server"、組件未正確參考檢查註冊指令、組件參考、建置輸出路徑

結語

復合控制項是 ASP.NET 2.0 打造可重用、封裝良好、設計時友善 UI 元件的利器。掌握 CompositeControl 基類機制、CreateChildControls 生命週期、頂層介面暴露技巧與設計時擴充,即可將複雜 UI 邏輯封裝為「拖曳即用」的專業級控制項,大幅提升團隊開發效率與程式碼品質。

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