Поделиться через


Добавление клиентских возможностей серверным веб-элементам управления

Обновлен: Ноябрь 2007

Технология AJAX в ASP.NET позволяет расширить возможности веб-приложений, предоставляя более широкие функциональные возможности взаимодействия с пользователем. ECMAScript (JavaScript), DHTML и технологию AJAX можно использовать для включения визуальных эффектов, клиентской обработки, например, проверки и т.д.

В этом разделе рассматривается создание пользовательского веб-элемента управления, использующего возможности AJAX платформы ASP.NET для расширения функциональных возможностей веб-обозревателя. Функциональные возможности можно добавлять в клиентскую объектную модель документов (DOM) с помощью клиентского элемента управления. Клиентский элемент управления может быть связан с серверным элементом управления с помощью реализации интерфейса IScriptControl в серверном элементе управления.

В этом разделе вы узнаете, как выполнять следующие задачи.

  • Создание серверного веб-элемента управления, который инкапсулирует поведение клиента и содержит свойства, задаваемые пользователями для управления поведением.

  • Создание клиентского элемента управления, который связан с серверным веб-элементом управления.

  • Обработка событий модели DOM веб-обозревателя в клиентском элементе управления.

    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    Кроме того, серверным веб-элементам управления можно добавить богатые клиентские возможности путем создания управляющего элемента-расширителя. Управляющий элемент-расширитель инкапсулирует в своем поведении клиентские возможности и затем присоединяется к серверному веб-элементу управления. Поскольку управляющий элемент-расширитель не является частью связанного с ним элемента управления, можно создать один управляющий элемент-расширитель, который может быть связан с несколькими типами серверных веб-элементов управления. Пример см. в разделе Создание управляющего элемента-расширителя для связи клиентского расширения функциональности с серверным веб-элементом управления.

  • Компиляция пользовательского управляющего веб-элемента в сборку и включение в данную сборку связанных файлов JavaScript в качестве ресурсов.

  • Создание ссылок на скомпилированный пользовательский веб-элемент управления на веб-странице ASP.NET с поддержкой AJAX.

Определение требований клиентов

При добавлении клиентского поведения серверному веб-элементу управления необходимо сперва решить, каким будет поведение элемента управления в веб-обозревателе. Затем необходимо определить функциональные возможности клиента, необходимые для реализации поведения.

Серверный веб-элемент управления, созданный в данном разделе, реализует простую функциональность клиента. В веб-обозревателе элемент управления TextBox будет подсвечиваться при выборе (или при фокусе). Например, элемент управления может изменять цвет фона при получении фокуса и затем возвращать цвет по умолчанию при переходе фокуса на другой элемент управления.

Для реализации такой функциональности клиентскому элементу управления необходимы возможности, перечисленные в следующей таблице.

  • Способ подсветки элемента DOM.
    Чтобы выделить элемент DOM на странице ASP.NET методом подсветки, клиентский элемент управления применяет стиль из каскадной таблицы стилей (CSS), который определяется именем класса. Данный стиль настраивается пользователем.

  • Способ возвращения элемента DOM в состояние без подсветки.
    Чтобы убрать подсветку элемента DOM на веб-странице ASP.NET, клиентский элемент управления применяет стиль каскадных таблиц стилей (CSS), который определяется именем класса. Данный стиль настраивается пользователем и применяется к элементу DOM как стиль по умолчанию.

  • Способ определения выбора пользователем элемента DOM.
    Для определения, выбран ли элемент DOM (имеет ли он фокус), элемент управления обрабатывает событие onfocus элемента DOM.

  • Способ определения отсутствия выбора элемента DOM.
    Для определения отсутствия фокуса на элементе DOM элемент управления обрабатывает событие onblur элемента DOM.

Создание серверного веб-элемента управления

Серверный веб-элемент управления, включающий клиентские возможности с использованием функциональности технологии AJAX в ASP.NET, аналогичен любому другому серверному веб-элементу управления. Однако элемент управления также реализует интерфейс IScriptControl из пространства имен System.Web.UI. В данном разделе элемент управления расширяет функциональные возможности элемента управления ASP.NET TextBox путем наследования класса TextBox и реализации интерфейса IScriptControl.

В следующем примере показано, как определить класс.

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

Новый серверный веб-элемент управления содержит два свойства, используемые для реализации требований клиента:

  • HighlightCssClass, определяющее класс CSS, который будет применяться к элементу DOM для его выделения при наличии фокуса.

  • NoHighlightCssClass, определяющее класс CSS, который будет применяться к элементу DOM, не имеющему фокуса.

Реализация интерфейса IScriptControl

В следующей таблице перечислены члены интерфейса IScriptControl, которые необходимо реализовать в серверном веб-элементе управления.

  • GetScriptDescriptors
    Возвращает коллекцию объектов ScriptDescriptor, которые содержат сведения об экземплярах клиентских компонентов, использующихся с серверным веб-элементом управления. Сюда входят создаваемые клиентские типы, назначаемые свойства и события, для которых добавляются обработчики.

  • GetScriptReferences
    Возвращает коллекцию объектов ScriptReference, содержащих сведения о библиотеках клиентских сценариев, которые должны быть включены в элемент. Библиотеки клиентских сценариев определяют типы клиентов и любой другой код JavaScript, который требуется для реализации требуемого поведения.

В данном разделе серверный веб-элемент управления для определения экземпляра типа клиентского элемента управления использует метод GetScriptDescriptors. Данный элемент управления создает новый объект ScriptControlDescriptor (класс ScriptControlDescriptor является производным от класса ScriptDescriptor) и включает объект в значение, возвращаемое методом GetScriptDescriptors.

Объект ScriptControlDescriptor включает имя класса клиента (Samples.SampleTextBox) и значение ClientID для серверного веб-элемента управления. Данное значение используется как id для отображаемого элемента DOM. Имя клиентского класса и значение свойства ClientID передаются в конструктор объекта ScriptControlDescriptor.

Класс ScriptControlDescriptor используется для задания значения свойств клиентского элемента управления, которые извлекаются из свойств серверного веб-элемента управления. Для определения свойств клиентского элемента управления, серверный веб-элемент управления использует метод ScriptComponentDescriptor.AddProperty класса ScriptControlDescriptor. Затем серверный веб-элемент управления указывает имя и значение свойства клиентского элемента управления на основе соответствующего свойства серверного веб-элемента управления. В данном примере объект ScriptControlDescriptor используется для задания значений свойств highlightCssClass и nohighlightCssClass в клиентском элементе управления.

Серверный веб-элемент управления замещает объект ScriptControlDescriptor в значении, возвращаемом методом GetScriptDescriptors. Таким образом, когда серверный веб-элемент управления отображается в веб-обозревателе, ASP.NET отображает JavaScript, который создает экземпляр клиентского элемента управления со всеми заданными свойствами и обработчиками событий. Экземпляр элемента управления присоединяется к элементу DOM, основываясь на свойстве ClientID, которое взято из серверного веб-элемента управления. В следующем примере представлена декларативная разметка ASP.NET, включающая серверный веб-элемент управления из данного раздела.

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

В выходных данных при отображении страницы содержится вызов метода $create, который идентифицирует создаваемый клиентский класс. Кроме того, выходные данные содержат значения клиентских свойств и значение id объекта DOM, с которым связан клиентский элемент. В следующем примере приведен метод $create.

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

Пример серверного веб-элемента управления использует метод GetScriptReferences для передачи расположения библиотеки сценариев, которая определяет тип клиентского элемента управления. В данном примере это URL-адрес к файлу сценария с именем SampleTextBox.js, который будет создан позже. Ссылка создается путем создания нового объекта ScriptReference и установки в качестве значения свойства Path URL-адреса файла, содержащего код клиента.

В следующем примере показана реализация методов GetScriptDescriptors и GetScriptReferences.

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 для текущей страницы. Регистрация выполняется с помощью вызова метода RegisterScriptControl<TScriptControl> класса ScriptManager и указания ссылки на клиентский элемент управления.

Пример серверного веб-элемента управления регистрируется как клиентский элемент управления в элементе управления ScriptManager на странице. Для этого элемент переопределяет метод OnPreRender базового элемента управления TextBox. Затем он вызывает метод RegisterScriptControl(), чтобы зарегистрировать себя в качестве клиентского элемента управления. Кроме того элемент управления регистрирует дескрипторы сценария, созданные методом GetScriptDescriptors. Это выполняется путем вызова метода RegisterScriptDescriptors() в методе Render элемента управления.

В следующем примере показаны вызовы методов 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);
}

В следующем примере показан полный код серверного веб-элемента управления.

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();
        }
    }
}

Создание клиентского элемента управления

В серверном элементе управления метод GetScriptReferences задает файл JavaScript (SampleTextBox.js), содержащий код клиента для типа элемента управления. В данном подразделе описан код JavaScript этого файла.

Код клиентского элемента управления соответствует членам, которые заданы в объектах ScriptDescriptor, возвращаемых методом GetScriptDescriptors. Клиентский элемент управления может также содержать члены, которые не соответствуют членам в классе серверного веб-элемента управления.

Пример серверного веб-элемента управления задает имя клиентского элемента управления Samples.SampleTextBox и определяет два свойства клиентского элемента управления: highlightCssClass и nohighlightCssClass.

Дополнительные сведения о создании клиентских компонентов и элементов управления см. в разделе Создание клиентского класса компонентов с помощью модели прототипа.

Регистрация клиентского пространства имен

Для регистрации клиентского пространства имен (Samples) код клиентского элемента управления должен сначала вызвать метод registerNamespace класса Type. В следующем примере показано, как зарегистрировать клиентское пространство имен.

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

Определение клиентского класса

После регистрации клиентского пространства имен код определяет класс Samples.SampleTextBox. Данный класс содержит два свойства для хранения значений свойств, предоставляемых серверным веб-элементом управления. Кроме того, класс содержит два делегата события, которые задают обработчики для событий onfocus и onblur элемента DOM, которые связаны с элементом управления Samples.SampleTextBox.

В следующем примере показано определение класса Samples.SampleTextBox.

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

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

Определение прототипа класса

После определения класса Samples.SampleTextBox клиентский код определяет прототип данного класса. Прототип включает функции доступа "get" и "set" для свойств, а также обработчики событий. Кроме того, прототип содержит метод initialize, вызываемый при создании экземпляра элемента управления, и метод dispose, который выполняет очистку при отсутствии необходимости в наличии элемента управления на странице.

Определение обработчиков событий для элемента DOM

Обработчики событий для клиентского класса определяются как методы прототипа класса. Данные обработчики связаны с делегатами событий и с событиями веб-обозревателя DOM с помощью методов addHandlers и 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" для свойства

Каждое свойство, определенное в объекте ScriptDescriptor метода GetScriptDescriptors серверного веб-элемента управления, должно обладать соответствующими клиентскими методами доступа. Клиентские методы доступа свойства определяются как методы get_<property name> и set_<property name> прототипа клиентского класса.

Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

Язык JavaScript является регистрозависимым. Имена методов доступа get и set должны точно соответствовать именам свойств, определенным в объекте ScriptDescriptor метода GetScriptDescriptors в серверном веб-элементе управления.

В следующем примере показаны методы доступа свойств get и set для элемента Samples.SampleTextBox.

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 вызывается при создании экземпляра элемента управления. Данный метод служит для задания значения свойств по умолчанию, создания функций делегатов и добавления делегатов в качестве обработчиков событий.

Метод initialize класса Samples.SampleTextBox выполняет следующие действия:

  • Вызывает метод initialize базового класса Sys.UI.Control.

  • Вызывает метод addHandlers для добавления делегатов событий в качестве обработчиков событий onfocus и onblur связанного HTML-элемента (<input type="text">). Часть имени события "on" (например, onfocus) не указывается.

Метод dispose вызывается, когда экземпляр элемента управления больше не используется на странице и его необходимо удалить. Данный метод служит для освобождения любых ресурсов, которые больше не требуются элементу управления, например, обработчики событий DOM.

Метод dispose класса Sample.SampleTextBox выполняет следующие действия:

  • Вызывает метод clearHandlers для очистки делегатов событий как обработчиков событий onfocus и onblur связанного элемента DOM.

  • Вызывает метод dispose базового класса Control.

    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    Метод dispose клиентского класса может вызываться несколько раз. Убедитесь, что код, включенный в метод dispose, учитывает этот факт.

В следующем примере показана реализация методов initialize и dispose прототипа Samples.SampleTextBox.

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.

В следующем примере показан вызов метода registerClass элемента управления Samples.SampleTextBox. В примере также показан вызов метода notifyScriptLoaded объекта Sys.Application. Данный вызов необходим для того, чтобы Microsoft AJAX (библиотека) получила уведомление о загрузке файла 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();

Динамическая компиляция управляющего элемента для тестирования

Любой серверный веб-элемент управления, например элемент управления из данного раздела, необходимо скомпилировать, прежде чем ссылаться на него на веб-странице. Для тестирования серверных веб-элементов управления без ручной компиляции в сборку можно использовать функцию динамической компиляции ASP.NET версии 2.0. Данная функция позволяет сэкономить время, затрачиваемое при написании и отладке кода серверного веб-элемента управления. На следующих этапах показано, как использовать папку App_Code для динамической компиляции элемента управления.

Размещение элемента управления в папке App_Code для динамической компиляции

  1. Создайте папку App_Code в корневой папке веб-узла.

  2. Переместите исходные CS- или VB-файлы элемента управления и все связанные классы в папку App_Code

    - или -

    Если сборка для элемента управления была ранее добавлена в папку Bin, удалите эту сборку. Продолжайте редактирование исходных файлов в папке App_Code. Исходный код элемента управления будет компилироваться при каждом запуске проекта.

    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    Можно выполнить предварительную компиляцию элемента управления в сборку и поместить сборку в папку Bin либо поместить исходные файлы элемента управления в папку App_Code, но не то и другое сразу. Если элемент управления добавить в обе папки, то анализатор страниц не сможет разрешить ссылку на данный элемент управления на странице и возникнет ошибка.

  3. Откройте веб-страницу.

    Элемент управления будет динамически скомпилирован.

Тестирование динамически скомпилированного элемента управления на веб-странице

Следующая процедура описывает тестирование элемента управления на странице ASP.NET с поддержкой AJAX. Код для серверного веб-элемента управления динамически компилируется в папке App_Code.

Использование поведения на странице ASP.NET

  1. Создайте новую страницу ASP.NET.

  2. Если на ней еще нет элемента управления ScriptManager, добавьте его.

  3. Создайте правила стилей CSS для выделяемых и не выделяемых текстовых полей.

    Элемент управления можно выделять как угодно. Например, можно изменять цвет фона элемента управления, добавлять границу или изменять шрифт текста.

  4. Добавьте на страницу директиву @ Register, а затем укажите пространство имен и атрибут TagPrefix для элемента управления, как показано в следующем примере.

    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    В данном случае код серверного веб-элемента управления находится в папке App_Code, поэтому он может компилироваться динамически. Следовательно, атрибут сборки не указывается.

  5. Добавьте на страницу элементы управления TextBox и Button и задайте свойство ID для каждого из них.

    В разметку для элементов управления необходимо добавить строку runat="server".

  6. Добавьте на страницу экземпляр элемента управления FocusExtender.

  7. Установите в качестве значения свойства TargetControlID элемента управления FocusExtender идентификатор элемента управления Button, который был добавлен ранее.

  8. Установите для свойства HighlightCssClass стиль CSS с выделением, а для свойства NoHighlightCssClass — стиль CSS без выделения.

  9. Запустите страницу и последовательно выбирайте каждый элемент управления.

    При выборе элемента управления Button он выделяется.

В следующем примере показана страница ASP.NET, которая использует функциональность, созданную в этом разделе.

Компиляция элемента управления в сборку

Внедрение компонента JavaScript и кода расширения серверного веб-элемента управления в сборку поможет упростить развертывание пользовательского элемента управления. Создание сборки также облегчает управление версиями элемента управления. Кроме того, элементы управления невозможно добавить на панель элементов конструктора до тех пор, пока они не будут скомпилированы в сборку.

В следующей процедуре описывается создание новой библиотеки кода в существующем учебном проекте с помощью Visual Studio. Будет выполнено перемещение копий файлов кода в новую библиотеку в проекте для данного раздела. Компиляция элемента управления в библиотеку кода приведет к созданию сборки, для которой можно выполнить развертывание.

Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

Для выполнения данной процедуры необходимо использовать Microsoft Visual Studio 2005. Нельзя использовать Visual Web Developer 2005, экспресс-выпуск, поскольку Visual Web Developer, экспресс-выпуск не позволяет создавать два проекта в одном решении.

Добавление новой библиотеки кода в существующий проект

  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")]
    
    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    Файл AssemblyInfo.vb находится в узле Мой проект обозревателя решений. Если в узле Мой проект нет никаких файлов, то в меню Проект выберите пункт Показать все файлы. Файл AssemblyInfo.cs находится в узле Свойства обозревателя решений.

    Определение WebResource для файлов JavaScript должно соответствовать соглашению о допустимых именах [пространство_имен_сборки].[имя_файла_JavaScript].js.

    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    По умолчанию Visual Studio устанавливает в качестве имени пространства имен сборки имя этой сборки. Пространство имен сборки можно изменить в свойствах сборки.

  5. В файле класса SampleTextBox измените объект ScriptReference в методе GetScriptReferences, чтобы он ссылался на клиентский сценарий элемента управления, внедренный в сборку "Samples". Для этого внесите следующие изменения:

    • Замените свойство Path свойством Assembly, имеющим значение "Samples".

    • Добавьте свойство 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) внедряется в эту сборку в качестве ресурса.

    Bb386450.alert_note(ru-ru,VS.90).gifПримечание.

    Следует помнить о том, что каждый раз при добавлении новых файлов кода или изменении существующих необходимо выполнять построение этого проекта библиотеки классов заново.

Использование скомпилированного элемента управления из сборки на веб-странице

На данном этапе будет создана ссылка на скомпилированный пользовательский элемент управления на веб-странице ASP.NET с поддержкой AJAX.

Создание ссылки на пользовательский элемент управления на странице ASP.NET с поддержкой AJAX

  1. Создайте новый проект AJAX ASP.NET.

  2. В корневом каталоге веб-узла создайте папку Bin.

  3. Скопируйте сборку Samples.dll из папки Bin\Debug или Bin\Release проекта библиотеки классов "Samples" в новую папку Bin.

  4. Добавьте новую ASP.NET веб-страницу с именем TestSampleTextBoxAssembly.aspx, а затем добавьте следующую разметку на новую страницу.

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

    Так как серверный элемент управления компилируется в сборку, директива @ Register содержит атрибут Assembly, который ссылается на сборку "Samples" в дополнение к атрибутам Namespace и TagPrefix.

  5. Запустите страницу и последовательно выбирайте каждый элемент управления.

    При выборе элемента управления SampleTextBox он выделяется.

Веб-страница, использующая скомпилированный пользовательский элемент управления, включает атрибут Assembly в директиве @ Register. В остальном это та же страница, которая использовалась для элемента управления в папке App_Code.

См. также

Основные понятия

Создание управляющего элемента-расширителя для связи клиентского расширения функциональности с серверным веб-элементом управления

Использование элемента управления UpdatePanel ASP.NET с элементами управления с привязкой к данным

Ссылки

Класс Sys.UI.Control

IScriptControl

ScriptManager