共用方式為


建立自訂的 AJAX 用戶端控制項

更新:2007 年 11 月

本概觀說明如何建立自訂 ASP.NET AJAX 用戶端控制項以及如何在網頁中使用。在本概觀中,您將了解如何進行下列作業:

  • 在 ECMAScript (JavaScript) 中使用原型設計模式定義控制項類別。

  • 將控制項註冊為衍生自 Sys.UI.Control 基底類別的類別。

  • 初始化 Control 基底類別和叫用其方法。

  • 建立網頁開發人員可繫結和處理的自訂事件。

  • 在網頁中使用用戶端控制項,並繫結至控制項的事件。

這個概觀提供完整用戶端控制項的範例,這個控制項會建立具有停留行為的按鈕。

這個概觀著重在用戶端控制項。ASP.NET AJAX 用戶端元件物件有三種類型:

  • 衍生自 Sys.Component 基底類別且沒有 UI 表示的隱藏式元件。

  • 衍生自 Sys.UI.Behavior 的行為。

  • 衍生自 Control 的控制項。

下表摘要說明元件、行為與控制項之間的差異。

用戶端元件物件型別

摘要

元件

  • Component 基底類別衍生。

  • 通常沒有 UI 表示,例如計時器元件會定期引發事件,但不會在網頁上看到此元件。

  • 沒有關聯的 DOM 項目。

  • 封裝可跨應用程式重複使用的用戶端程式碼。

行為

  • Behavior 基底類別衍生,該類別延伸 Component 基底類別。

  • 延伸 DOM 項目的行為,例如可附加到現有的文字方塊的浮水印行為。

  • 可以建立 UI 項目,但通常不會修改附加行為的關聯 DOM 項目的標記。

  • 若指派 ID,可從 DOM 項目透過自訂屬性 (expando) 直接存取。

  • 不需要與另一個用戶端物件的關聯,例如從 ControlBehavior 類別衍生的類別。

  • 可以在其 element 屬性參考控制項或非控制項 HTML 項目。

控制項

  • Control 基底類別衍生,該類別延伸 Component 基底類別。

  • 以用戶端物件表示的 DOM 項目,通常是變更原始 DOM 項目的一般行為以提供新功能。例如,功能表控制項可能會從 ul 項目 (Element) 讀取 li 項目 (Item),以做為其來源資料,但不會顯示項目符號清單。

  • 可由 DOM 項目透過控制項 expando 直接存取。

必要條件

若要執行此主題提供的用戶端控制項範例,您需要:

建立自訂 ASP.NET AJAX 用戶端控制項的基本功能

ASP.NET AJAX 用戶端控制項以用戶端物件表示 DOM 項目,並為該項目延伸標記表示或提供其他功能。例如,用戶端控制項可能延伸 HTML 項目,藉由套用不同的 CSS 樣式來反應滑鼠事件。

用戶端控制項封裝可跨應用程式重複使用的 JavaScript 程式碼。從 Control 基底類別衍生您的自訂控制項,控制項就會自動繼承許多內建的跨瀏覽器功能,包括:

  • 能夠為控制項相關的 DOM 項目加入和移除事件處理常式,以及加入和移除控制項本身的事件處理常式。

  • 自動將控制項註冊為可處置物件,這個物件實作 Sys.IDisposable 介面。

  • 當屬性變更時引發通知事件的功能。

  • 能夠執行控制項屬性設定的批次處理。對於指令碼大小與處理時間,這種方式比使用個別屬性 get 與 set 存取子 (Accessor) 處理所有邏輯來得有效率。

實作用戶端控制項

下表摘要說明實作自訂用戶端控制項的步驟,該控制項衍生自 Control。表格後面說明每個步驟的詳細資訊。

步驟

摘要

使用原型設計模式定義用戶端控制項類別。

  1. 註冊控制項類別的命名空間。

  2. 定義控制項的建構函式來接收 DOM 項目引數,並定義原型。

  3. 將控制項函式註冊為衍生自 Control 基底類別的類別。

初始化控制項的基底 Control 執行個體,並傳遞關聯的 DOM 項目做為引數。

  • 在控制項的建構函式中,呼叫其繼承的 Type.initializeBase 方法,並將建構函式引數中接收的 DOM 項目傳遞至基底類別。

公開 (Expose) 任何屬性存取子,並選擇性地引發 Sys.Component.propertyChanged 通知事件。

  • 在元件的原型中使用 get 和 set 存取子方法公開屬性。

  • 對於任何屬性,如果變更的通知非常重要,請從屬性的 set 存取子中引發 propertyChanged 通知事件。

覆寫 Sys.UI.Control.initialize 方法以初始化任何屬性與事件接聽程式 (Event Listener)。

如果元件或 DOM 項目需要初始化任何屬性或事件接聽程式,請覆寫元件原型中的 initialize 方法。在覆寫方法中,請執行下列動作:

  • 呼叫 Sys.UI.DomEvent.addHandler 方法,將任何委派加入至 window 物件或項目的 DOM 事件。

  • 設定任何初始 DOM 項目屬性。

  • 設定任何可及性屬性,例如 DOM 項目上的定位點索引或控制項的 role 屬性。

  • 呼叫基底類別的 initialize 方法。

覆寫 Sys.UI.Control.dispose 方法以釋放資源,例如移除 DOM 事件處理常式。

如果在處置 (Dispose) 控制項之前需要釋放任何資源,請覆寫元件原型中的 dispose 方法。在覆寫方法中,請執行下列動作:

  • 停止控制項可能在內部排入佇列的任何處理序,並停用公開至呼叫端的任何功能。

  • 在處置控制項之前移除 DOM 事件處理常式。清除您的控制項所設定的任何 DOM 項目處理常式,可移除對這些 DOM 項目的循環參考,並釋放為這些項目保留的記憶體。

  • 呼叫基底 dispose 方法。dispose 方法中的所有程式碼必須可多次呼叫。例如,在嘗試釋放資源前,驗證資源尚未釋放。

使用原型設計模式定義控制項類別

在 JavaScript 中使用原型設計模式定義包含控制項類別的 ASP.NET AJAX 用戶端類別。如需詳細資訊,請參閱 使用原型模型建立用戶端元件類別

用戶端控制項類別必須衍生自 Control 基底類別。使用 Type.registerClass 方法,將 ASP.NET AJAX 用戶端類別註冊為用戶端應用程式的類別。如需詳細資訊,請參閱 Type.registerClass 方法

初始化基底類別

在控制項的建構函式中初始化基底 Control 物件。在控制項的建構函式中,叫用繼承的 initializeBase 方法,並將建構函式引數中接收的 DOM 項目傳遞至基底類別。通常是在建構函式中執行其他任何程式碼之前叫用 initializeBase 方法。初始化 Control 基底類別後,其方法可供控制項使用,且會自動使用 Sys.Application 執行個體將控制項註冊為可處置物件。如需詳細資訊,請參閱 Sys.IDisposable 介面

下列範例顯示衍生自 Control 之控制項的建構函式。元件的建構函式會呼叫繼承的 initializeBase 方法。

Samples.SimpleControl = function(element)
{
    Samples.SimpleControl.initializeBase(this, [element]);
}

定義屬性和引發屬性變更通知

您可以在用戶端控制項的類別中,定義可供網頁開發人員取得和設定的屬性。您也可以為元件的屬性引發 propertyChanged 通知事件。使用您元件的網頁開發人員就可以繫結至這些事件。衍生自 ComponentBehaviorControl 基底類別的 ASP.NET AJAX 元件會繼承 Sys.Component.raisePropertyChanged 方法,您可以呼叫這個方法來引發 propertyChanged 事件。如需詳細資訊,請參閱定義自訂元件屬性和引發 PropertyChanged 事件

初始化屬性與事件接聽程式

如果自訂控制項必須初始化所有屬性或事件接聽程式,請覆寫元件原型中的 initialize 方法。衍生自 Control 基底類別的用戶端控制項,通常會將任何處理常式繫結至其 DOM 項目事件,並將 DOM 項目屬性設定為初始值。在最後的步驟中,您必須呼叫基底 initialize 方法,讓元件的基底類別完成初始設定。

釋放資源

如果自訂控制項必須在處置控制項之前釋放資源,請覆寫 dispose 方法,並在覆寫方法中釋放資源。這樣可確保在處置控制項之前會立即釋放資源。釋放的資源包括用來繫結至 DOM 事件的處理常式。為了確保可從記憶體中移除物件,請驗證已移除 DOM 項目與元件物件之間可能的任何循環參考。如需詳細資訊,請參閱釋放元件資源

在網頁中使用控制項

若要在 ASP.NET Web 網頁中使用自訂用戶端控制項,您必須執行下列動作:

  • 在 Web 網頁中註冊用戶端控制項的指令碼程式庫。

  • 建立用戶端控制項執行個體。

以下章節提供關於這些步驟的詳細資訊。

在 Web 網頁中註冊控制項的指令碼程式庫

您可以在網頁上使用 ScriptManager 控制項,以宣告方式或程式設計方式註冊用戶端控制項所需的指令碼。

下列範例說明 ScriptManager 控制項的宣告式標記,這個控制項可註冊控制項指令碼。

<form id="form1" >
  <asp:ScriptManager  ID="ScriptManager01">
    <scripts>
      <asp:ScriptReference path="HoverButton.js" />
    </scripts>
  </asp:ScriptManager>
</form>

asp:ScriptManager 項目在 scripts 節點內包含 asp:ScriptReference 項目。asp:ScriptReference 項目的 path 屬性參考 HoverButton.js 檔案的路徑,這個檔案定義控制項類別。如需詳細資訊,請參閱動態指派指令碼參考ScriptManager 類別概觀。

注意事項:

所有以 ScriptManager 控制項註冊的獨立指令碼檔案都必須呼叫 notifyScriptLoaded 方法,通知應用程式指令碼已完成載入。在大部分情況下,內嵌在組件 (Assembly) 中的指令碼不應該呼叫此方法。如需詳細資訊,請參閱Sys.Application.notifyScriptLoaded 方法

除了使用 ScriptManager 控制項註冊指令碼檔案之外,您也可以使用實作 IScriptControl 介面的自訂伺服器控制項來管理用戶端元件。自訂伺服器控制項可以自動註冊所需的元件指令碼,並公開宣告式標記以設定元件屬性與事件繫結。這樣可讓網頁開發人員更容易使用您的自訂控制項。如需詳細資訊,請參閱 IScriptControl 類別概觀。

建立自訂控制項執行個體

您可以在 Sys.Application.init 事件期間透過呼叫 Sys.Component.create 方法或 $create 捷徑來產生自訂用戶端控制項。下表說明您建立用戶端控制項時傳遞至 $create 方法的參數。

參數

描述

type

元件類型。

properties

JSON 物件,包含元件 ID 值和任何選擇性初始屬性名稱/值組。

events

選擇性 JSON 物件,包含事件名稱和事件/處理常式繫結組。

references

選擇性 JSON 物件,包含關聯元件的參考,當做元件名稱/ID 組傳遞。

element

要與控制項產生關聯的 DOM 項目。

下列範例顯示如何呼叫 $create 方法來產生控制項執行個體。

$create(Demo.HoverButton, {text: 'A HoverButton Control',element: {style: {fontWeight: "bold", borderWidth: "2px"}}}, {click: start, hover: doSomethingOnHover, unhover: doSomethingOnUnHover},null, $get('Button1'));

如需詳細資訊,請參閱 Sys.Component.create 方法Sys.Component $create 方法

建立自訂 HoverButton 控制項

在本章節中,您將延伸 Control 基底類別建立簡單的自訂用戶端控制項,名為 HoverButton,然後在網頁中使用這個控制項。HoverButton 控制項會攔截相關聯 HTML button 項目的 clickfocusmouseover 事件。也提供可透過 $create 方法繫結的事件給控制項。使用 HoverButton 控制項的網頁開發人員可以繫結至控制項的 hover 事件。

建立 HoverButton 控制項的程式碼

  1. 在具備 AJAX 能力的 ASP.NET 網站的根目錄中,建立名為 HoverButton.js 的檔案。

  2. 將下列程式碼加入至該檔案中:

    Type.registerNamespace("Demo");
    
    // Constructor
    Demo.HoverButton = function(element) {
    
        Demo.HoverButton.initializeBase(this, [element]);
    
        this._clickDelegate = null;
        this._hoverDelegate = null;
        this._unhoverDelegate = null;
    }
    Demo.HoverButton.prototype = {
    
        // text property accessors.
        get_text: function() {
            return this.get_element().innerHTML;
        },
        set_text: function(value) {
            this.get_element().innerHTML = value;
        },
    
        // Bind and unbind to click event.
        add_click: function(handler) {
            this.get_events().addHandler('click', handler);
        },
        remove_click: function(handler) {
            this.get_events().removeHandler('click', handler);
        },
    
        // Bind and unbind to hover event.
        add_hover: function(handler) {
            this.get_events().addHandler('hover', handler);
        },
        remove_hover: function(handler) {
            this.get_events().removeHandler('hover', handler);
        },
    
        // Bind and unbind to unhover event.
        add_unhover: function(handler) {
            this.get_events().addHandler('unhover', handler);
        },
        remove_unhover: function(handler) {
            this.get_events().removeHandler('unhover', handler);
        },
    
        // Release resources before control is disposed.
        dispose: function() {
    
            var element = this.get_element();
    
            if (this._clickDelegate) {
                Sys.UI.DomEvent.removeHandler(element, 'click', this._clickDelegate);
                delete this._clickDelegate;
            }
    
            if (this._hoverDelegate) {
                Sys.UI.DomEvent.removeHandler(element, 'focus', this._hoverDelegate);
                Sys.UI.DomEvent.removeHandler(element, 'mouseover', this._hoverDelegate);
                delete this._hoverDelegate;
            }
    
            if (this._unhoverDelegate) {
                Sys.UI.DomEvent.removeHandler(element, 'blur', this._unhoverDelegate);
                Sys.UI.DomEvent.removeHandler(element, 'mouseout', this._unhoverDelegate);
                delete this._unhoverDelegate;
            }
            Demo.HoverButton.callBaseMethod(this, 'dispose');
        },
    
        initialize: function() {
    
            var element = this.get_element();
    
            if (!element.tabIndex) element.tabIndex = 0;
    
            if (this._clickDelegate === null) {
                this._clickDelegate = Function.createDelegate(this, this._clickHandler);
            }
            Sys.UI.DomEvent.addHandler(element, 'click', this._clickDelegate);
    
            if (this._hoverDelegate === null) {
                this._hoverDelegate = Function.createDelegate(this, this._hoverHandler);
            }
            Sys.UI.DomEvent.addHandler(element, 'mouseover', this._hoverDelegate);
            Sys.UI.DomEvent.addHandler(element, 'focus', this._hoverDelegate);
    
            if (this._unhoverDelegate === null) {
                this._unhoverDelegate = Function.createDelegate(this, this._unhoverHandler);
            }
            Sys.UI.DomEvent.addHandler(element, 'mouseout', this._unhoverDelegate);
            Sys.UI.DomEvent.addHandler(element, 'blur', this._unhoverDelegate);
    
            Demo.HoverButton.callBaseMethod(this, 'initialize');
    
        },
        _clickHandler: function(event) {
            var h = this.get_events().getHandler('click');
            if (h) h(this, Sys.EventArgs.Empty);
        },
        _hoverHandler: function(event) {
            var h = this.get_events().getHandler('hover');
            if (h) h(this, Sys.EventArgs.Empty);
        },
        _unhoverHandler: function(event) {
            var h = this.get_events().getHandler('unhover');
            if (h) h(this, Sys.EventArgs.Empty);
        }
    }
    Demo.HoverButton.registerClass('Demo.HoverButton', Sys.UI.Control);
    
    // Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
    // invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
    // that this is the end of the script.
    if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
    
    

程式碼討論

程式碼會透過呼叫 Type.registerNamespace 方法來註冊 Demo 命名空間。建構函式會叫用繼承的 initializeBase 方法,使 Control 基底類別方法可供使用。接著,初始化的基底類別會將 Demo.HoverButton 執行個體註冊為用戶端應用程式的可處置物件。

在原型中,程式碼會宣告公用事件 click、hover 和 unhover。網頁開發人員可以加入和移除接聽這些事件的處理常式。接著,這些方法會透過控制項的事件處理常式集合,加入或移除指定的處理常式。您可以透過控制項的 Sys.EventHandlerList 物件,在您的控制項類別中加入和移除處理常式。EventHandlerList 物件會經由繼承的 Sys.Component.events 屬性,取得控制項的事件處理常式集合。在這個範例中,程式碼會叫用傳回的 EventHandlerList 物件的 Sys.EventHandlerList.addHandlerSys.EventHandlerList.removeHandler 方法,以加入或移除處理常式。

HoverButton 類別覆寫基底 dispose 方法,在處置控制項之前,安全地處置任何控制項資源 (例如 DOM 事件的處理常式)。最後,程式碼會呼叫基底 dispose 方法,讓應用程式釋放控制項。

在 Web 網頁中使用 HoverButton 控制項

在本章節中,您將學習如何在 Web 網頁中使用用戶端指令碼建立控制項執行個體。

建立網頁來使用 HoverButton 控制項

  1. 在您放置 HoverButton.js 檔案的應用程式根目錄中,建立名為 DemoHoverButton.aspx 的檔案。

  2. 將下列標記和程式碼加入至這個檔案:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head id="Head1" >
    
        <style type="text/css">
            button {border: solid 1px black}
            #HoverLabel {color: blue}
        </style>
        <title>Control Demo</title>
    </head>
    <body>
        <form id="form1" >
            <div id="ResultDisplay"></div>
    
                <asp:ScriptManager  ID="ScriptManager01">
                    <scripts>
                       <asp:ScriptReference Path="HoverButton.js" />
                    </scripts>
                </asp:ScriptManager>
    
                <script type="text/javascript">
                    var app = Sys.Application;
                    app.add_init(applicationInitHandler);
    
                    function applicationInitHandler(sender, args) {
                        $create(Demo.HoverButton, {text: 'A HoverButton Control',element: {style: {fontWeight: "bold", borderWidth: "2px"}}}, {click: start, hover: doSomethingOnHover, unhover: doSomethingOnUnHover},null, $get('Button1'));
                    }
    
                    function doSomethingOnHover(sender, args) {
                        hoverMessage = "The mouse is over the button."
                        $get('HoverLabel').innerHTML = hoverMessage;
                    }
    
                    function doSomethingOnUnHover(sender, args) {
                       $get('HoverLabel').innerHTML = "";
                    }
    
                    function start(sender, args) {
                       alert("The start function handled the HoverButton click event.");
                    }
                </script>
    
                <button type="button" id="Button1"></button>&nbsp;
            <div id="HoverLabel"></div>
        </form>
    
    </body>
    </html>
    

程式碼討論

DemoHoverButton.aspx 檔案是裝載自訂控制項的 ASP.NET Web 網頁。在這個網頁中,script 項目定義繫結至自訂控制項的函式。在 Sys.Application.init 事件處理常式中,用戶端指令碼會呼叫 $create 方法來產生 HoverButton 控制項。程式碼會將下列引數傳遞至 $create 方法:

  • type 引數包含您稍早建立的 Demo.HoverButton 類別。

  • properties 引數包含 JSON 物件,這個物件包含必要的控制項 ID 值,後面接著指定屬性名稱和初始值的屬性名稱值組。

  • events 引數包含一個物件,這個物件包含事件名稱及其處理常式。

ScriptManager 控制項中,asp:ScriptReference 節點的 path 屬性會參考 HoverButton.js 檔案的路徑,這個檔案定義 Demo.HoverButton 控制項類別。

設定 DOM 項目事件處理常式和元件事件處理常式

ASP.NET 中的 AJAX 功能包含類別,這些類別為元件和 DOM 項目提供標準化事件管理。您可以使用 Sys.EventHandlerList 類別的成員,例如 addHandlerremoveHandler,以管理控制項的事件。如需詳細資訊,請參閱 Sys.EventHandlerList 類別概觀。

您可以使用 Sys.UI.DomEvent 類別的靜態方法 (addHandlerremoveHandler),管理 DOM 項目或 window 物件事件的事件處理常式。如需詳細資訊,請參閱 Sys.UI.DomEvent 類別概觀。

存取 DOM 項目屬性

Sys.UI.DomElement 類別包含的成員,可讓您為用戶端控制項和項目加入、移除和切換 CSS 類別關聯。這些成員也提供 DOM 項目屬性的標準化存取。如需詳細資訊,請參閱 Sys.UI.DomElement 類別

請參閱

工作

建立自訂的隱藏式用戶端元件

動態指派指令碼參考

概念

搭配資料繫結控制項使用 ASP.NET UpdatePanel 控制項

使用 PageRequestManager 事件

參考

Sys.Component 類別

ScriptManager