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

Managed C++ 開發自訂 Web 組合控件:從零打造可複用的 SearchControl

     編輯:關於C++

ASP.NET 自訂組合控件將多個伺服器控件封裝為單一單元,支援設計器拖曳、屬性視窗編輯、工具箱整合與 WYSIWYG 預覽。雖然開發門檻高於 User Control(需手寫程式碼、無視覺化設計器),但編譯後僅需部署單一組件(.dll),跨專案複用極為便利。本文以 SearchControl 為例,完整演示 Managed C++ 開發流程。

核心架構:繼承 WebControl 並實作 INamingContainer

#pragma once
using namespace System;
using namespace System::Web::UI;
using namespace System::Web::UI::WebControls;

[DefaultProperty("Value"), DefaultEvent("Click"),
 ToolboxData("<{0}:SearchControl runat=server>")]
public __gc class SearchControl : public WebControl {
    // 子控件宣告
    Label* label;
    TextBox* textbox;
    Button* button;
    TableCell* cellLabel;  // 用於版面配置控制

public:
    SearchControl() {
        label = new Label();
        textbox = new TextBox();
        button = new Button();
        cellLabel = new TableCell();
    }

    // 必須覆寫:建立子控件樹
    void CreateChildControls() override {
        Table* table = new Table();
        TableRow* row = new TableRow();
        TableCell* cell2 = new TableCell();
        TableCell* cell3 = new TableCell();

        cellLabel->Controls->Add(label);
        textbox->Width = Unit::Percentage(100);  // 文字框自適應寬度
        cell2->Controls->Add(textbox);
        cell3->Width = Unit::Percentage(1);      // 按鈕欄位最小寬度
        cell3->Controls->Add(button);

        row->Cells->Add(cellLabel);
        row->Cells->Add(cell2);
        row->Cells->Add(cell3);
        table->Rows->Add(row);
        table->Width = Unit::Percentage(100);
        Controls->Add(table);
    }

    // Render 直接委派基類,子控件自行繪製
    void Render(HtmlTextWriter* output) override {
        __super::Render(output);
    }

屬性封裝:透過 EnsureChildControls 確保子控件就緒


    // LabelText 屬性
    [Bindable(true), Category("Appearance"), DefaultValue("")]
    __property String* get_LabelText() {
        EnsureChildControls();
        return label->Text;
    }
    __property void set_LabelText(String* value) {
        EnsureChildControls();
        label->Text = value;
    }

    // Value 屬性(綁定至 TextBox)
    [Bindable(true), Category("Appearance"), DefaultValue("")]
    __property String* get_Value() {
        EnsureChildControls();
        return textbox->Text;
    }
    __property void set_Value(String* value) {
        EnsureChildControls();
        textbox->Text = value;
    }

    // ButtonText 屬性
    [Bindable(true), Category("Appearance"), DefaultValue("")]
    __property String* get_ButtonText() {
        EnsureChildControls();
        return button->Text;
    }
    __property void set_ButtonText(String* value) {
        EnsureChildControls();
        button->Text = value;
    }

    // 版面控制屬性
    [Bindable(true), Category("Appearance")]
    __property Unit get_LabelWidth() {
        EnsureChildControls();
        return cellLabel->Width;
    }
    __property void set_LabelWidth(Unit value) {
        EnsureChildControls();
        cellLabel->Width = value;
    }

    [Bindable(true), Category("Appearance")]
    __property HorizontalAlign get_LabelAlign() {
        EnsureChildControls();
        return cellLabel->HorizontalAlign;
    }
    __property void set_LabelAlign(HorizontalAlign value) {
        EnsureChildControls();
        cellLabel->HorizontalAlign = value;
    }

事件機制:包裝按鈕 Click 並對外暴露


    // 建構子中綁定按鈕事件
    SearchControl() {
        // ... 初始化子控件 ...
        button->Click += new EventHandler(this, &SearchControl::buttonClicked);
    }

    void buttonClicked(Object* sender, EventArgs* e) {
        OnClick(e);  // 觸發對外事件
    }

    // 受保護虛擬方法,允許衍生類擴充
    protected: void OnClick(EventArgs* e) {
        if (Click != 0) Click(this, e);
    }

    // 對外公開的事件
    public: __event EventHandler* Click;
};

設計器中繼資料與使用範例

屬性 [DefaultProperty("Value"), DefaultEvent("Click")] 讓設計器雙擊控件自動產生 Click 事件處理函式。修改中繼資料後須「移除參考→重新加入參考」使設計器重新載入。

使用端程式碼 (C#):

private void SearchControl1_Click(object sender, System.EventArgs e) {
    WebCustomControl1.Text = SearchControl1.Value;
}

關鍵技術總結

技術點Managed C++ 實作要點
子控件建立覆寫 CreateChildControls,使用 Controls->Add 建立樹狀結構
版面配置採用 Table/TableRow/TableCell 控制對齊與自適應寬度
屬性封裝__property + EnsureChildControls() 確保子控件已建立
事件包裝內部處理子控件事件 → 呼叫 OnXxx → 觸發 __event
設計器整合ToolboxData、DefaultProperty、DefaultEvent 屬性
部署優勢單一 .dll、GAC 部署、多專案共用、版本控管容易

Managed C++ 雖已被 C++/CLI 取代,但其組合控件開發模式仍具參考價值:封裝複雜度、對外簡潔介面、設計器友善、部署獨立,是企業級控件庫開發的標準範式。

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