將用戶端功能加入至 Web 伺服器控制項

更新:2007 年 11 月

ASP.NET 中的 AJAX 功能可讓您擴充 Web 應用程式的功能,以創造更豐富的使用者經驗。您可以使用 Web 瀏覽器的 ECMAScript (JavaScript)、DHTML 與 AJAX 功能,加入多種視覺效果以及用戶端處理 (例如,驗證) 等。

本主題說明如何建立自訂 Web 伺服器控制項,這個控制項會使用 ASP.NET 瀏覽器中擴充功能的 AJAX 功能。您可以使用用戶端控制項將功能加入用戶端的文件物件模型 (DOM) 項目中。藉由在伺服器控制器中實作 IScriptControl 介面,用戶端控制項可以與伺服器控制項建立關聯。

在本主題中,您將會了解如何進行下列作業:

  • 建立 Web 伺服器控制項,該控制項可封裝用戶端行為,並包含使用者可用來設定控制項行為的屬性。

  • 建立用戶端控制項,該行為與 Web 伺服器控制項關聯。

  • 在用戶端控制項中處理來自瀏覽器 DOM 的事件。

    注意事項:

    您也可以藉由建立擴充項控制項,為 Web 伺服器控制項加入豐富的用戶端功能。此擴充項控制項可在一項行為中封裝多個用戶端功能,然後附加至 Web 伺服器控制項。因為擴充項控制項並不是其相關聯控制項的一部分,所以您可以建立單一擴充項控制項,使之與數種類型的 Web 伺服器控制項關聯。如需範例,請參閱建立擴充項控制項讓用戶端行為與 Web 伺服器控制項產生關聯

  • 將自訂 Web 伺服器控制項編譯為組件,並內嵌關聯的 JavaScript 檔案做為該相同組件中的資源。

  • 參考具備 ASP.NET AJAX 能力的 Web 網頁中編譯的自訂 Web 伺服器控制項。

識別用戶端需求

將用戶端行為加入至 Web 伺服器控制項的第一個步驟是,決定瀏覽器中將要出現哪種控制項行為。接著,您可以決定實作該行為所需的用戶端功能。

在本主題中建立的 Web 伺服器控制項只會實作簡單的用戶端行為。當控制項 (TextBox 控制項) 在瀏覽器中被選取 (或取得焦點) 時,該控制項就會反白顯示。例如,控制項取得焦點時可能會變更背景色彩,而當焦點移動到其他控制項時會還原為預設色彩。

為了能夠實作這個行為,本主題中的用戶端控制項需要下表列出的功能。

  • 反白顯示 DOM 項目的方式。
    用戶端控制項會套用階層式樣式表 (CSS) 樣式 (由類別名稱識別),以反白顯示 ASP.NET Web 網頁中的 DOM 項目。使用者可自行設定此樣式。

  • 將 DOM 項目還原為非反白顯示狀態的方式。
    為從 ASP.NET Web 網頁中的 DOM 項目移除反白顯示,用戶端控制項會套用 CSS 樣式,該樣式可由類別名稱識別。使用者可自行設定此樣式,接著將此樣式套用至 DOM 項目做為預設樣式。

  • 識別 DOM 項目何時被選取的方式。
    為識別 DOM 項目何時被選取 (取得焦點),控制項必須處理 DOM 項目的 onfocus 事件。

  • 識別何時取消選取 DOM 的方式。
    為識別何時取消選取控制項,控制項必須處理 DOM 項目的 onblur 事件。

建立 Web 伺服器控制項

藉由使用 ASP.NET AJAX 功能來包含用戶端功能的 Web 伺服器控制項,就如其他 Web 伺服器控制項一樣。不過,該控制項也會從 System.Web.UI 命名空間實作 IScriptControl 介面。本主題中的控制項會繼承 TextBox 類別並且實作 IScriptControl 介面,從而擴充 ASP.NET TextBox 控制項。

下列範例說明類別定義。

Public Class SampleTextBox
    Inherits TextBox
    Implements IScriptControl
public class SampleTextBox : TextBox, IScriptControl

新的 Web 伺服器控制項包含兩個屬性,這些屬性可用於實作用戶端需求:

  • HighlightCssClass,它識別當 DOM 項目取得焦點時將套用的 CSS 類別,以便反白顯示控制項。

  • NoHighlightCssClass,它識別當焦點移開 DOM 項目時將套用的 CSS 類別。

實作 IScriptControl 介面

下表列出 IScriptControl 介面的成員,您必須在 Web 伺服器控制項中實作該類別。

  • GetScriptDescriptors
    傳回 ScriptDescriptor 物件的集合,該物件包含搭配 Web 伺服器控制項使用之用戶端元件執行個體 (Instance) 的相關資訊。這包含要建立的用戶端類型、要指派的屬性,以及要加入處理常式的事件。

  • GetScriptReferences
    傳回 ScriptReference 物件的集合,該物件包含控制項將包含之用戶端指令碼程式庫的相關資訊。用戶端指令碼程式庫定義用戶端類型與該行為所需的任何其他 JavaScript 程式碼。

本主題中的 Web 伺服器控制項使用 GetScriptDescriptors 方法來定義用戶端控制項類型的執行個體。控制項會建立新的 ScriptControlDescriptor 物件 (從 ScriptDescriptor 類別衍生的 ScriptControlDescriptor 類別),並包含 GetScriptDescriptors 方法之傳回值中的物件。

ScriptControlDescriptor 物件包含用戶端類別 (Samples.SampleTextBox) 的名稱,以及 Web 伺服器控制項的 ClientID 值。此值用來做為所呈現 DOM 項目的 id 值。用戶端類別名稱與 ClientID 屬性值會傳遞至 ScriptControlDescriptor 物件的建構函式。

ScriptControlDescriptor 類別用來設定用戶端控制項的屬性值,這些值會從 Web 伺服器控制項的屬性中取得。為定義用戶端控制項的屬性,Web 伺服器控制項會使用 ScriptControlDescriptor 類別的 ScriptComponentDescriptor.AddProperty 方法。接著,Web 伺服器控制項會根據對應的 Web 伺服器控制項屬性,來指定用戶端控制項屬性的名稱與值。此範例使用 ScriptControlDescriptor 物件來設定用戶端控制項中 highlightCssClass 與 nohighlightCssClass 屬性的值。

Web 伺服器控制項會提供傳回值中的 ScriptControlDescriptor 物件,以用於 GetScriptDescriptors 方法。因此,當 Web 伺服器控制項呈現在瀏覽器時,ASP.NET 會呈現 JavaScript,該指令碼使用所有定義的屬性與事件處理常式來建立用戶端控制項的執行個體。控制項執行個體會根據 ClientID 屬性 (從 Web 伺服器控制項呈現) 附加到 DOM 項目。下列範例顯示宣告式 ASP.NET 標記,該標記包含來自網頁中本主題的 Web 伺服器控制項。

<sample:SampleTextBox 
  ID="SampleTextBox1"
  HighlightCssClass="MyHighLight"
  NoHighlightCssClass="MyLowLight" />

呈現的網頁輸出包含 $create 方法的呼叫,該方法可識別要建立的用戶端控制項。它也會提供用戶端屬性的值,以及與用戶端控制項關聯之 DOM 物件的 id 值。下列範例顯示呈現的 $create 方法。

$create(Samples.SampleTextBox, {"highlightCssClass":"MyHighLight","nohighlightCssClass":"MyLowLight"}, null, null, $get('SampleTextBox1'));

範例 Web 伺服器控制項使用 GetScriptReferences 方法來傳遞指令碼程式庫的位置,該程式庫會定義用戶端控制項類型。在此範例中,這是名為 SampleTextBox.js 指令碼檔案的 URL,您會於稍後建立該指令碼檔案。此參考的產生方式是建立新的 ScriptReference 物件,然後將 Path 屬性設定為包含用戶端程式碼之檔案的 URL。

下列範例顯示 GetScriptDescriptorsGetScriptReferences 方法的實作。

Protected Overridable Function GetScriptReferences() As IEnumerable(Of ScriptReference)
    Dim reference As ScriptReference = New ScriptReference()
    reference.Path = ResolveClientUrl("SampleTextBox.js")

    Return New ScriptReference() {reference}
End Function

Protected Overridable Function GetScriptDescriptors() As IEnumerable(Of ScriptDescriptor)
    Dim descriptor As ScriptControlDescriptor = New ScriptControlDescriptor("Samples.SampleTextBox", Me.ClientID)
    descriptor.AddProperty("highlightCssClass", Me.HighlightCssClass)
    descriptor.AddProperty("nohighlightCssClass", Me.NoHighlightCssClass)

    Return New ScriptDescriptor() {descriptor}
End Function

Function IScriptControlGetScriptReferences() As IEnumerable(Of ScriptReference) Implements IScriptControl.GetScriptReferences
    Return GetScriptReferences()
End Function

Function IScriptControlGetScriptDescriptors() As IEnumerable(Of ScriptDescriptor) Implements IScriptControl.GetScriptDescriptors
    Return GetScriptDescriptors()
End Function
protected virtual IEnumerable<ScriptReference> GetScriptReferences()
{
    ScriptReference reference = new ScriptReference();
    reference.Path = ResolveClientUrl("SampleTextBox.js");

    return new ScriptReference[] { reference };
}

protected virtual IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
    ScriptControlDescriptor descriptor = new ScriptControlDescriptor("Samples.SampleTextBox", this.ClientID);
    descriptor.AddProperty("highlightCssClass", this.HighlightCssClass);
    descriptor.AddProperty("nohighlightCssClass", this.NoHighlightCssClass);

    return new ScriptDescriptor[] { descriptor };
}

IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
    return GetScriptReferences();
}

IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
    return GetScriptDescriptors();
}

註冊用戶端控制項

用戶端控制項必須向目前頁面的 ScriptManager 物件註冊。藉由呼叫 ScriptManager 類別的 RegisterScriptControl<TScriptControl> 方法,並提供參考給用戶端控制項,即可完成此動作。

範例 Web 伺服器控制項會向頁面上的 ScriptManager 控制項,將自己註冊為用戶端控制項。為了這麼做,該控制項會覆寫基底 TextBox 控制項的 OnPreRender 方法。然後它會呼叫 RegisterScriptControl() 方法,以便將自己註冊為用戶端控制項。此外,控制項也會註冊指令碼描述項,該描述項是使用 GetScriptDescriptors 方法建立的。它完成此動作的方法是在控制項的 Render 方法中呼叫 RegisterScriptDescriptors() 方法。

下列範例顯示 RegisterScriptControl() 與 RegisterScriptDescriptors() 方法的呼叫。

Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
    If Not Me.DesignMode Then

        ' Test for ScriptManager and register if it exists
        sm = ScriptManager.GetCurrent(Page)

        If sm Is Nothing Then _
            Throw New HttpException("A ScriptManager control must exist on the current page.")

        sm.RegisterScriptControl(Me)
    End If

    MyBase.OnPreRender(e)
End Sub

Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
    If Not Me.DesignMode Then _
      sm.RegisterScriptDescriptors(Me)

    MyBase.Render(writer)
End Sub
protected override void OnPreRender(EventArgs e)
{
    if (!this.DesignMode)
    {
        // Test for ScriptManager and register if it exists
        sm = ScriptManager.GetCurrent(Page);

        if (sm == null)
            throw new HttpException("A ScriptManager control must exist on the current page.");

        sm.RegisterScriptControl(this);
    }

    base.OnPreRender(e);
}

protected override void Render(HtmlTextWriter writer)
{
    if (!this.DesignMode)
        sm.RegisterScriptDescriptors(this);

    base.Render(writer);
}

下列範例顯示 Web 伺服器控制項的完整程式碼。

Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Collections.Generic

Namespace Samples.VB

    Public Class SampleTextBox
        Inherits TextBox
        Implements IScriptControl

        Private _highlightCssClass As String
        Private _noHighlightCssClass As String
        Private sm As ScriptManager

        Public Property HighlightCssClass() As String
            Get
                Return _highlightCssClass
            End Get
            Set(ByVal value As String)
                _highlightCssClass = value
            End Set
        End Property

        Public Property NoHighlightCssClass() As String
            Get
                Return _noHighlightCssClass
            End Get
            Set(ByVal value As String)
                _noHighlightCssClass = value
            End Set
        End Property

        Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
            If Not Me.DesignMode Then

                ' Test for ScriptManager and register if it exists
                sm = ScriptManager.GetCurrent(Page)

                If sm Is Nothing Then _
                    Throw New HttpException("A ScriptManager control must exist on the current page.")

                sm.RegisterScriptControl(Me)
            End If

            MyBase.OnPreRender(e)
        End Sub

        Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
            If Not Me.DesignMode Then _
              sm.RegisterScriptDescriptors(Me)

            MyBase.Render(writer)
        End Sub

        Protected Overridable Function GetScriptReferences() As IEnumerable(Of ScriptReference)
            Dim reference As ScriptReference = New ScriptReference()
            reference.Path = ResolveClientUrl("SampleTextBox.js")

            Return New ScriptReference() {reference}
        End Function

        Protected Overridable Function GetScriptDescriptors() As IEnumerable(Of ScriptDescriptor)
            Dim descriptor As ScriptControlDescriptor = New ScriptControlDescriptor("Samples.SampleTextBox", Me.ClientID)
            descriptor.AddProperty("highlightCssClass", Me.HighlightCssClass)
            descriptor.AddProperty("nohighlightCssClass", Me.NoHighlightCssClass)

            Return New ScriptDescriptor() {descriptor}
        End Function

        Function IScriptControlGetScriptReferences() As IEnumerable(Of ScriptReference) Implements IScriptControl.GetScriptReferences
            Return GetScriptReferences()
        End Function

        Function IScriptControlGetScriptDescriptors() As IEnumerable(Of ScriptDescriptor) Implements IScriptControl.GetScriptDescriptors
            Return GetScriptDescriptors()
        End Function
    End Class
End Namespace
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;

namespace Samples.CS
{
    public class SampleTextBox : TextBox, IScriptControl
    {
        private string _highlightCssClass;
        private string _noHighlightCssClass;
        private ScriptManager sm;

        public string HighlightCssClass
        {
            get { return _highlightCssClass; }
            set { _highlightCssClass = value; }
        }

        public string NoHighlightCssClass
        {
            get { return _noHighlightCssClass; }
            set { _noHighlightCssClass = value; }
        }

        protected override void OnPreRender(EventArgs e)
        {
            if (!this.DesignMode)
            {
                // Test for ScriptManager and register if it exists
                sm = ScriptManager.GetCurrent(Page);

                if (sm == null)
                    throw new HttpException("A ScriptManager control must exist on the current page.");

                sm.RegisterScriptControl(this);
            }

            base.OnPreRender(e);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (!this.DesignMode)
                sm.RegisterScriptDescriptors(this);

            base.Render(writer);
        }

        protected virtual IEnumerable<ScriptReference> GetScriptReferences()
        {
            ScriptReference reference = new ScriptReference();
            reference.Path = ResolveClientUrl("SampleTextBox.js");

            return new ScriptReference[] { reference };
        }

        protected virtual IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor("Samples.SampleTextBox", this.ClientID);
            descriptor.AddProperty("highlightCssClass", this.HighlightCssClass);
            descriptor.AddProperty("nohighlightCssClass", this.NoHighlightCssClass);

            return new ScriptDescriptor[] { descriptor };
        }

        IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
        {
            return GetScriptReferences();
        }

        IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
        {
            return GetScriptDescriptors();
        }
    }
}

建立用戶端控制項

在 Web 伺服器控制項中,GetScriptReferences 方法會指定 JavaScript 檔案 (SampleTextBox.js),該檔案包含控制項類型的用戶端程式碼。本節將說明該檔案中的 JavaScript 程式碼。

用戶端控制項程式碼必須與 ScriptDescriptor 物件 (由 GetScriptDescriptors 方法所傳回) 中指定的成員相符合。用戶端控制項也可以具有未對應至 Web 伺服器控制項類別成員的成員。

範例 Web 伺服器控制項會將用戶端控制項的名稱設定為 Samples.SampleTextBox,並且定義 highlightCssClass 與 nohighlightCssClass 這兩個用戶端控制項屬性。

如需如何建立用戶端元件與控制項的詳細資訊,請參閱使用原型模型建立用戶端元件類別

註冊用戶端命名空間

用戶端控制項程式碼必須先呼叫 Type 類別的 registerNamespace 方法,以註冊其命名空間 (Samples)。下列範例顯示如何註冊用戶端命名空間。

// Register the namespace for the control.
Type.registerNamespace('Samples');

定義用戶端類別

註冊用戶端命名空間之後,程式碼會定義 Samples.SampleTextBox 類別。此類別包含兩個屬性以保存 Web 伺服器控制項提供的屬性值。它也包含兩種事件委派,用來指定 onfocus 的處理常式,以及與 Samples.SampleTextBox 控制項關聯之 DOM 項目的 onblur 事件。

下列範例顯示 Samples.SampleTextBox 類別定義。

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

    this._highlightCssClass = null;
    this._nohighlightCssClass = null;
}

定義類別原型

定義 Samples.SampleTextBox 類別之後,用戶端程式碼會定義類別的原型。原型包含屬性的 get 與 set 存取子,以及事件處理常式。它也包含當建立控制項之執行個體時會呼叫的 initialize 方法,以及當網頁不再需要該控制項時會執行清除的 dispose 方法。

定義 DOM 項目的事件處理常式

用戶端類別的事件處理常式定義為類別原型的方法。處理常式會使用 addHandlers 方法來與事件委派及瀏覽器 DOM 事件建立關聯,本主題稍後會討論該方法與 initialize 方法。

下列範例顯示 Samples.SampleTextBox 控制項的事件處理常式方法。

_onFocus : function(e) {
    if (this.get_element() && !this.get_element().disabled) {
        this.get_element().className = this._highlightCssClass;          
    }
},

_onBlur : function(e) {
    if (this.get_element() && !this.get_element().disabled) {
        this.get_element().className = this._nohighlightCssClass;          
    }
},

定義 Get 屬性與 Set 方法

在 Web 伺服器控制項之 GetScriptDescriptors 方法的 ScriptDescriptor 物件中識別的每個屬性,都必須具有對應的用戶端存取子。用戶端屬性存取子會定義為用戶端類別原型的 get_<property name> 與 set_<property name> 方法。

注意事項:

JavaScript 是區分大小寫的。get 與 set 存取子名稱必須完全符合在 Web 伺服器控制項之 GetScriptDescriptors 方法的 ScriptDescriptor 物件中識別的屬性名稱。

下列範例顯示 Samples.SampleTextBox 控制項的 get 屬性與 set 存取子。

get_highlightCssClass : function() {
    return this._highlightCssClass;
},

set_highlightCssClass : function(value) {
    if (this._highlightCssClass !== value) {
        this._highlightCssClass = value;
        this.raisePropertyChanged('highlightCssClass');
    }
},

get_nohighlightCssClass : function() {
    return this._nohighlightCssClass;
},

set_nohighlightCssClass : function(value) {
    if (this._nohighlightCssClass !== value) {
        this._nohighlightCssClass = value;
        this.raisePropertyChanged('nohighlightCssClass');
    }
}

實作 Initialize 與 Dispose 方法

建立控制項的執行個體時,會呼叫 initialize 方法。您可以使用此方法來設定預設屬性值、建立函式委派,以及將委派加入為事件處理常式。

Samples.SampleTextBox 類別的 initialize 方法會執行下列動作:

  • 呼叫 Sys.UI.Control 基底類別的 initialize 方法。

  • 呼叫 addHandlers 方法新增事件委派,做為關聯 HTML 項目 ((<input type="text">) 之 onfocus 與 onblur 事件的處理常式。事件名稱的 "on" 部分 (例如,onfocus) 不會指定。

當網頁上控制項的執行個體不再使用且已移除時,便會呼叫 dispose 方法。使用此方法可以釋出控制項不再需要的任何資源,例如 DOM 事件處理常式。

Sample.SampleTextBox 類別的 dispose 方法會執行下列動作:

  • 呼叫 clearHandlers 方法以清除關聯之 DOM 項目的 onfocus 與 onblur 事件處理常式的事件委派。

  • 呼叫 Control 基底類別的 dispose 方法。

    注意事項:

    您可以呼叫多次用戶端類別的 dispose 方法。確定您包含在 dispose 方法的程式碼已將此列入考量。

下列範例顯示 Samples.SampleTextBox 原型之 initialize 與 dispose 方法的實作。

initialize : function() {
    Samples.SampleTextBox.callBaseMethod(this, 'initialize');

    this._onfocusHandler = Function.createDelegate(this, this._onFocus);
    this._onblurHandler = Function.createDelegate(this, this._onBlur);

    $addHandlers(this.get_element(), 
                 { 'focus' : this._onFocus,
                   'blur' : this._onBlur },
                 this);

    this.get_element().className = this._nohighlightCssClass;
},

dispose : function() {
    $clearHandlers(this.get_element());

    Samples.SampleTextBox.callBaseMethod(this, 'dispose');
},

註冊控制項

建立用戶端控制項的最後一個工作是呼叫 registerClass 方法以註冊用戶端類別。因為類別是用戶端控制項,所以 registerClass 方法的呼叫會包含要註冊的 JavaScript 類別名稱。它也會指定 Control 做為基底類別。

下列範例顯示 Samples.SampleTextBox 控制項之 registerClass 方法的呼叫。此範例也包含 Sys.Application 物件之 notifyScriptLoaded 方法的呼叫。需要此呼叫才能通知 Microsoft AJAX Library 已載入 JavaScript 檔案。

Samples.SampleTextBox.registerClass('Samples.SampleTextBox', Sys.UI.Control);

if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

下列範例顯示 Samples.SampleTextBox 用戶端控制項的完整程式碼。

// Register the namespace for the control.
Type.registerNamespace('Samples');

//
// Define the control properties.
//
Samples.SampleTextBox = function(element) { 
    Samples.SampleTextBox.initializeBase(this, [element]);

    this._highlightCssClass = null;
    this._nohighlightCssClass = null;
}

//
// Create the prototype for the control.
//

Samples.SampleTextBox.prototype = {


    initialize : function() {
        Samples.SampleTextBox.callBaseMethod(this, 'initialize');

        this._onfocusHandler = Function.createDelegate(this, this._onFocus);
        this._onblurHandler = Function.createDelegate(this, this._onBlur);

        $addHandlers(this.get_element(), 
                     { 'focus' : this._onFocus,
                       'blur' : this._onBlur },
                     this);

        this.get_element().className = this._nohighlightCssClass;
    },

    dispose : function() {
        $clearHandlers(this.get_element());

        Samples.SampleTextBox.callBaseMethod(this, 'dispose');
    },

    //
    // Event delegates
    //

    _onFocus : function(e) {
        if (this.get_element() && !this.get_element().disabled) {
            this.get_element().className = this._highlightCssClass;          
        }
    },

    _onBlur : function(e) {
        if (this.get_element() && !this.get_element().disabled) {
            this.get_element().className = this._nohighlightCssClass;          
        }
    },


    //
    // Control properties
    //

    get_highlightCssClass : function() {
        return this._highlightCssClass;
    },

    set_highlightCssClass : function(value) {
        if (this._highlightCssClass !== value) {
            this._highlightCssClass = value;
            this.raisePropertyChanged('highlightCssClass');
        }
    },

    get_nohighlightCssClass : function() {
        return this._nohighlightCssClass;
    },

    set_nohighlightCssClass : function(value) {
        if (this._nohighlightCssClass !== value) {
            this._nohighlightCssClass = value;
            this.raisePropertyChanged('nohighlightCssClass');
        }
    }
}

// Optional descriptor for JSON serialization.
Samples.SampleTextBox.descriptor = {
    properties: [   {name: 'highlightCssClass', type: String},
                    {name: 'nohighlightCssClass', type: String} ]
}

// Register the class as a type that inherits from Sys.UI.Control.
Samples.SampleTextBox.registerClass('Samples.SampleTextBox', Sys.UI.Control);

if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

動態編譯控制項以進行測試

任何 Web 伺服器控制項 (例如,本主題中的控制項) 都必須經過編譯,您才能在 Web 網頁中參考它。您可以使用 ASP.NET 2.0 版的動態編譯功能測試 Web 伺服器控制項,而不需要以手動方式將這些控制項編譯為組件。當您首次撰寫 Web 伺服器控制項程式碼並進行偵錯時,這樣可以節省時間。下列步驟顯示如何使用 App_Code 資料夾來動態編譯控制項。

將控制項置於 App_Code 資料夾以進行動態編譯

  1. 在網站的根資料夾下建立 [App_Code] 資料夾。

  2. 將 .cs 或 .vb 控制項原始程式檔與任何相關類別移動到 [App_Code] 資料夾。

    -或-

    如果先前已將控制項的組件加入至 [Bin] 資料夾,請刪除該組件。您可以繼續編輯 [App_Code] 資料夾中的原始程式檔。每當您執行您的專案時,都會編譯控制項原始程式碼。

    注意事項:

    您可以將控制項預先編譯為組件並將組件置於 [Bin] 資料夾,或者將控制項的原始程式檔置於 [App_Code] 資料夾,但是無法同時執行這兩項動作。如果在這兩個資料夾中都加入了該控制項,網頁剖析器將無法解析網頁中的控制項參考,進而引發錯誤。

  3. 執行 Web 網頁。

    此時會動態編譯控制項。

測試 Web 網頁中動態編譯的控制項

下列程序說明如何在具備 ASP.NET AJAX 能力的 Web 網頁中,測試控制項。Web 伺服器控制項的程式碼會從 [App_Code] 資料夾動態編譯。

在 ASP.NET 網頁中使用該行為

  1. 建立新 ASP.NET Web 網頁。

  2. 如果網頁沒有 ScriptManager 控制項,請新增一個。

  3. 為已反白顯示的文字方塊與未反白顯示的文字方塊建立 CSS 樣式規則。

    您可以使用想要的方式來反白顯示控制項。例如,您可以變更控制項的背景色彩、加入框線,或變更文字字型。

  4. @ Register 指示詞加入到網頁中,然後指定控制項的命名空間與 TagPrefix 屬性,如下範例所示。

    注意事項:

    在這個案例中,伺服器控制項程式碼位於 [App_Code] 資料夾,以便進行動態編譯。因此,未指定組件屬性。

  5. TextBoxButton 控制項加入網頁中,並設定其 ID 屬性。

    控制項的標記必須包含 。

  6. 將 FocusExtender 控制項的執行個體加入網頁中。

  7. 將 FocusExtender 控制項的 TargetControlID 屬性設定為您先前加入之 Button 控制項的識別碼。

  8. 將 HighlightCssClass 屬性設定為反白顯示的 CSS 樣式,並將 NoHighlightCssClass 屬性設定為不反白顯示的 CSS 樣式。

  9. 執行此頁面並選取每一個控制項。

    當您選取 Button 控制項時,它會反白顯示。

下列範例顯示的 ASP.NET 網頁,使用了本主題中建立的行為。

將控制項編譯為組件

將 JavaScript 元件與 Web 伺服器控制項擴充程式碼內嵌到組件中,可讓您的自訂控制項更容易部署。建立組件也可以讓控制項版本控制的管理作業變得更簡單。此外,將控制項編譯為組件之前,無法將控制項加入至設計工具的工具箱中。

下列程序說明如何使用 Visual Studio,在現有的主題專案中建立新的程式碼程式庫。您必須將程式碼檔案的複本移動到本主題中專案的新程式碼程式庫。編譯程式碼程式庫中的控制項將會產生可供部署的組件。

注意事項:

若要執行此程序,您必須使用 Microsoft Visual Studio 2005。您無法使用 Visual Web Developer 2005 Express 版,因為 Visual Web Developer Express 版無法讓您在相同方案中建立兩個專案。

將新的程式碼程式庫加入到現有專案中

  1. 按一下 Visual Studio [檔案] 功能表上的 [新增],然後按一下 [專案]。

    [新增專案] 對話方塊隨即出現。

  2. 在 [專案類型] 底下,選取 [Visual C#] 或 [Visual Basic]。

  3. 在 [範本] 底下,選取 [類別庫],並將專案命名為 Samples。

  4. 在 [方案] 清單中,選取 [加入至方案],然後按一下 [確定]。

    Samples 類別程式庫會加入至現有的方案。

將自訂伺服器控制項移動到程式碼程式庫中

  1. 將下列參考加入到 Samples 類別程式庫專案,自訂伺服器控制項要求必須這樣做:

    • System.Drawing

    • System.Web

    • System.Web.Extensions

  2. 在 [方案總管] 中,將 SampleTextBox.cs 或 SampleTextBox.vb 檔案與 SampleTextBox.js 檔案,從原始專案中複製到 Samples 類別程式庫專案的根目錄。

  3. 在 SampleTextBox.js 檔案的 [屬性] 視窗中,將 [建置動作] 設定為 [內嵌資源]。

  4. 將下列屬性加入至 AssemblyInfo 檔案。

    <Assembly: WebResource("Samples.SampleTextBox.js", "text/javascript")>
    
    [assembly: System.Web.UI.WebResource("Samples.SampleTextBox.js", "text/javascript")]
    
    注意事項:

    AssemblyInfo.vb 檔案位於 [方案總管] 的 [我的專案] 節點內。如果您沒有在 [我的專案] 節點內看到任何檔案,請執行下列動作:按一下 [專案] 功能表上的 [顯示所有檔案]。AssemblyInfo.cs 檔案位於 [方案總管] 的 [屬性] 節點內。

    JavaScript 檔案的 WebResource 定義必須遵循 [assembly namespace].[JavaScript File name].js 的命名規範。

    注意事項:

    依照預設,Visual Studio 會將組件命名空間設定為組件名稱。您可以在組件的屬性中編輯組件命名空間。

  5. 在 SampleTextBox 類別檔案中,將 GetScriptReferences 方法中的 ScriptReference 物件變更為參考內嵌在 "Samples" 組件中的用戶端控制項指令碼。若要這樣做,請執行下列變更:

    • Assembly 屬性設定為 "Samples",以取代 Path 屬性。

    • 加入 Name 屬性,並將其值設定為 "Samples.SampleTextBox.js"。

    下列範例顯示此變更的結果。

            Protected Overridable Function GetScriptReferences() As IEnumerable(Of ScriptReference)
                Dim reference As ScriptReference = New ScriptReference()
                reference.Assembly = "Samples"
                reference.Name = "Samples.SampleTextBox.js"
    
                Return New ScriptReference() {reference}
            End Function
    
            protected virtual IEnumerable<ScriptReference> GetScriptReferences()
            {
                ScriptReference reference = new ScriptReference();
                reference.Assembly = "Samples";
                reference.Name = "Samples.SampleTextBox.js";
    
                return new ScriptReference[] { reference };
            }
    
  6. 建置專案。

    編譯完成時,您會得到名為 Samples.dll 的組件。JavaScript 程式碼檔案 (SampleTextBox.js) 會內嵌為此組件中的資源。

    注意事項:

    加入新的原始程式檔或變更現有的原始程式檔後,請記得務必重新建置類別程式庫專案。

使用 Web 網頁中之組件的已編譯控制項

您現在可以在具備 ASP.NET AJAX 能力的 Web 網頁中,參考已編譯的自訂控制項。

在具備 ASP.NET AJAX 能力的 Web 網頁中參考自訂控制項

  1. 建立新的 ASP.NET AJAX 專案。

  2. 在網站的根目錄下建立 [Bin] 資料夾。

  3. 將 Samples.dll 組件從 Samples 類別專案的 [Bin\Debug] 或 [Bin\Release] 資料夾複製到新的 [Bin] 資料夾。

  4. 加入名為 TestSampleTextBoxAssembly.aspx 的新 ASP.NET Web 網頁,然後將下列標記加入新網頁中。

    <%@ Register Assembly="Samples" Namespace="Samples.VB" TagPrefix="sample" %>
    
    <%@ Register Assembly="Samples" Namespace="Samples.CS" TagPrefix="sample" %>
    

    因為伺服器控制項會編譯為組件,所以 @ Register 指示詞具有 Assembly 屬性,該屬性除了參考 Namespace 與 TagPrefix 屬性之外,還會參考 "Samples" 組件。

  5. 執行此頁面並選取每一個控制項。

    當您選取 SampleTextBox 控制項時,它會反白顯示。

使用已編譯之自訂控制項的 Web 網頁,便會在 @ Register 指示詞中包含 Assembly 屬性。否則,它會與您用於 [App_Code] 資料夾之控制項的 Web 網頁相同。

請參閱

概念

建立擴充項控制項讓用戶端行為與 Web 伺服器控制項產生關聯

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

參考

Sys.UI.Control 類別

IScriptControl

ScriptManager