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

Visual Studio 2010

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

В этом обзоре показано, как создать пользовательский клиентский элемент управления ASP.NET AJAX и использовать его на странице. Из этого обзора можно узнать, как выполнить следующие действия:

  • Использовать прототип шаблона разработки в ECMAScript (JavaScript) для определения класса элемента управления.

  • Зарегистрировать элемент управления, как класс, производный от базового класса Sys.UI.Control.

  • Инициализировать базовый класс Control и вызвать его методы.

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

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

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

Этот обзор посвящен клиентским элементам управления. Существует три типа объектов клиентских компонентов ASP.NET AJAX:

  • Невизуальные компоненты, производные от базового класса Sys.Component и не имеющие представления пользовательского интерфейса.

  • Поведения, производные от Sys.UI.Behavior.

  • Элементы управления, производные от Control.

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

Типы объектов клиентских компонентов

Сводка

Компоненты

  • Производные от базового класса Component.

  • Обычно им не соответствуют элементы пользовательского интерфейса (например, компонент Timer, который периодически создает события, но не отображается на странице).

  • Не имеют связанных элементов DOM.

  • Инкапсулируют клиентский код, предназначенный для использования в различных приложениях.

Поведения

  • Производные от базового класса Behavior, расширяющего базовый класс Component.

  • Расширяют поведение элементов DOM (например, поведение отображения водяных знаков, которое можно присоединить к существующему текстовому полю).

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

  • При назначении идентификатора, к ним можно получить доступ непосредственно из элемента DOM с использованием настраиваемого атрибута (expando).

  • Не требуют связи с другим клиентским объектом, таким как класс, производный от классов Control или Behavior.

  • Могут ссылаться на элемент управления или на не управляющий элемент HTML в своем свойстве element .

Элементы управления

  • Производные от базового класса Control, расширяющего базовый класс Component.

  • Представляют элемент DOM как клиентский объект, часто меняя обычное поведение исходного элемента DOM и добавляя к нему новые функциональные возможности. Например, элемент управления меню может считывать элементы li из элемента ul как исходные данные, но не может отображать маркированный список.

  • Доступны непосредственно из элемента DOM с помощью элемента управления expando.

Для выполнения примера клиентского элемента управления, приведенного в этом разделе, понадобится следующее:

Клиентский элемент управления ASP.NET AJAX представляет элемент DOM как клиентский объект и расширяет представление разметки, или предоставляет элементу дополнительную функциональность. Например, клиентский элемент управления может расширить элемент HTML для реагирования на события мыши с помощью различных стилей CSS.

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

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

  • Автоматическая регистрация элемента управления как высвобождаемого объекта, реализующего интерфейс Sys.IDisposable.

  • Возможность вызывать события уведомления при изменении свойств.

  • Возможность выполнять пакетную обработку параметров свойства элемента управления. Это более эффективно с точки зрения размера сценария и времени обработки, чем обработка всей логики в методах доступа get и set для отдельного свойства.

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

Шаг

Сводка

Определение класса клиентского элемента управления, используя прототип шаблона разработки.

  1. Зарегистрируйте пространство имен для класса элемента управления.

  2. Определите функцию конструктора элемента управления для получения аргумента элемента DOM и определите прототип.

  3. Зарегистрируйте функцию элемента управления как класс, производный от базового класса Control.

Инициализация базового экземпляра элемента управления Control и передача связанного элемента DOM как аргумента.

  • В конструкторе элемента управления вызовите унаследованный им метод Type.initializeBase и передайте элемент DOM, полученный в аргументе конструктора, базовому элементу.

Предоставление методов доступа к свойствам и при необходимости вызов события уведомления Sys.Component.propertyChanged.

  • Предоставьте свойства в прототипе компонента посредством методов доступа get и set.

  • Для тех свойств, для которых может быть важно изменение уведомления, вызовите событие уведомления propertyChanged из метода доступа set свойства.

Переопределение метода Sys.UI.Control.initialize для инициализации свойств и прослушивателей событий.

Если необходимо инициализировать свойства или прослушиватели событий для компонента или элементов DOM, переопределите метод initialize в прототипе компонента. В переопределенном методе выполните следующее:

  • Добавьте делегаты к событиям DOM объекта window или элемента, вызвав метод Sys.UI.DomEvent.addHandler.

  • Задайте начальные свойства для элемента DOM.

  • Задайте свойства специальных возможностей, такие как индекс перехода по клавише TAB, для элемента DOM или атрибута role элемента управления.

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

Переопределение метода Sys.UI.Control.dispose для освобождения ресурсов, например, для удаления обработчиков событий DOM.

Если имеются ресурсы, которые необходимо освободить до удаления элемента управления, переопределите метод dispose в прототипе компонента. В переопределенном методе выполните следующее:

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

  • Удалите обработчики событий DOM до удаления элемента управления. При удалении обработчиков элементов DOM, заданных элементом управления, также будут удалены все циклические ссылки на эти элементы DOM и освобождена память, зарезервированная для этих элементов.

  • Вызовите базовый метод dispose. Весь код в методе dispose должен обладать способностью вызываться многократно. Например, до того, как попытаться освободить ресурс, убедитесь, что он уже не был освобожден.

Определение класса элемента управления при помощи прототипа шаблона разработки

Клиентский класс ASP.NET AJAX, включающий класс элемента управления, определяется в JavaScript при помощи прототипа шаблона разработки. Дополнительные сведения см. в разделе Создание клиентского класса компонентов с помощью модели прототипа.

Класс клиентских элементов управления должен быть производным от базового класса Control. Зарегистрируйте клиентский класс ASP.NET AJAX, как класс с клиентским приложением, используя метод Type.registerClass. Дополнительные сведения см. в разделе Метод Type.registerClass.

Инициализация базового класса

Базовый объект Control инициализируется в конструкторе элемента управления. В конструкторе элемента управления вызовите унаследованный метод initializeBase и передайте элемент DOM, полученный в аргументе конструктора, базовому классу. Обычно метод initializeBase вызывается до выполнения остального кода конструктора. При инициализации базового класса Control, его методы становятся доступны элементу управления, который автоматически регистрируется, как высвобождаемый объект с экземпляром Sys.Application. Дополнительные сведения см. в разделе Интерфейс Sys.IDisposable.

В следующем примере показана функция конструктора для элемента управления, производного от Control. Конструктор компонента вызывает унаследованный метод initializeBase.

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

Определение свойств и вызов уведомлений об изменении свойств

Определите свойства в клиентском классе элемента управления, которые разработчики страницы могут получать и задавать. Можно также вызвать события уведомления propertyChanged для этих свойств компонента. Разработчики страниц, использующие этот компонент, могут затем выполнить привязку к этим событиям. Компонент ASP.NET AJAX, производный от базового класса Component, Behavior или Control наследует метод Sys.Component.raisePropertyChanged, вызываемый для инициализации события propertyChanged. Дополнительные сведения см. в разделе Определение пользовательских свойств компонентов и создание событий PropertyChanged.

Инициализация свойств и прослушивателей событий

Если пользовательский элемент управления должен инициализировать свойства или прослушиватели событий, переопределите метод initialize в прототипе компонента. Клиентский элемент управления, производный от базового класса Control обычно привязывает обработчики к своим событиям элемента DOM и присваивает свойствам элемента DOM первоначальные значения. На последнем этапе вызовите базовый метод initialize для включения базового класса компонента, чтобы завершить инициализацию.

Освобождение ресурсов

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

Для использования пользовательского клиентского элемента управления на веб-странице ASP.NET сделайте следующее:

  • Зарегистрируйте библиотеку сценариев клиентского элемента управления на веб-странице.

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

В следующих подразделах подробно описаны этапы этой процедуры.

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

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

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

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

Элемент asp:ScriptManager содержит элемент asp:ScriptReference внутри узла scripts. Атрибут path элемента asp:ScriptReference ссылается на путь к файлу HoverButton.js, который определяет класс элемента управления. Дополнительные сведения см. в разделе Динамическое присваивание ссылок на сценарии и в общих сведениях о классе ScriptManager.

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

Все отдельные файлы библиотек, которые будут зарегистрированы элементом управления ScriptManager должны вызывать метод notifyScriptLoaded для уведомления приложения, что загрузка библиотеки завершена. Библиотеки, внедренные в сборку, чаще всего не должны вызывать этот метод. Дополнительные сведения см. в разделе Метод Sys.Application.notifyScriptLoaded.

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

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

Экземпляр пользовательского клиентского элемента управления создается путем вызова метода Sys.Component.create или псевдонима $create во время события Sys.Application.init. В следующей таблице описаны параметры, которые передаются методу $create при создании клиентского элемента управления.

Параметр

Описание

type

Тип компонента.

properties

Объект JSON, содержащий значение идентификатора компонента и, если необходимо, исходные пары "имя-значение" свойств.

events

Необязательный объект JSON, содержащий имя события и пары привязки "событие-обработчик".

references

Необязательный объект JSON, содержащий ссылки на связанные компоненты, переданные как пары "имя компонента-идентификатор".

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 перехватывает события click, focus, и mouseover связанного элемента HTML button. Он также обеспечивает элементы управления событиями, привязываемыми с помощью метода $create. Разработчик страницы, использующий элемент управления HoverButton, может выполнить привязку к событию hover этого элемента управления.

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

  1. В корневом каталоге веб-узла ASP.NET с поддержкой AJAX создайте файл с именем 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();
    
    
    
    

Рассмотрение кода

Этот код регистрирует пространство имен Demo, вызывая метод Type.registerNamespace. Конструктор вызывает унаследованный метод initializeBase, в результате чего становятся доступными методы базового класса Control. Инициализированный базовый класс в свою очередь регистрирует экземпляр Demo.HoverButton в клиентском приложении в виде высвобождаемого объекта.

В прототипе код объявляет открытые события click, hover и unhover. Разработчик страницы может добавлять и удалять обработчики, ожидающие эти события. Эти методы в свою очередь добавляют и удаляют указанный обработчик через коллекцию обработчика событий элемента управления. Добавлять обработчики в класс элемента управления или удалять их из него можно через объект элемента управления Sys.EventHandlerList. Объект EventHandlerList содержит коллекцию обработчиков событий элемента управления через унаследованное свойство Sys.Component.events. В этом примере код вызывает методы Sys.EventHandlerList.addHandler и Sys.EventHandlerList.removeHandler возвращаемого объекта EventHandlerList для добавления или удаления обработчиков.

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

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

Создание страницы для использования элемента управления 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" runat="server">
    
        <style type="text/css">
            button {border: solid 1px black}
            #HoverLabel {color: blue}
        </style>
        <title>Control Demo</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div id="ResultDisplay"></div>
    
                <asp:ScriptManager runat="server" 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, содержащей пользовательский элемент управления. На странице, функции, привязанные к пользовательскому элементу управления, определяются в элементе script. В обработчике событий Sys.Application.init экземпляр элемента управления HoverButton создается в клиентском сценарии путем вызова метода $create. Код передает методу $create следующие аргументы:

  • Аргумент type содержит созданный ранее класс Demo.HoverButton.

  • Аргумент properties содержит объект JSON, который содержит требуемое значение идентификатора элемента управления, за которым идут пары "имя-значение" свойства, указывающие имена свойств с начальными значениями.

  • Аргумент events содержит объект, содержащий пары имен событий с их обработчиками.

В элементе управления ScriptManager атрибут path узла asp:ScriptReference ссылается на путь к файлу HoverButton.js, который определяет класс элементов управления Demo.HoverButton.

Функциональность AJAX в ASP.NET включает классы, обеспечивающие стандартизированное управление событиями для компонентов и элементов DOM. Управлять событиями своих элементов управления можно при помощи членов класса Sys.EventHandlerList, таких как addHandler и removeHandler. Дополнительные сведения см. в общих сведениях о классе Sys.EventHandlerList.

Управлять обработчиками событий для элементов DOM или для событий объекта window можно при помощи статических методов класса Sys.UI.DomEvent: addHandler или removeHandler. Дополнительные сведения см. в общих сведениях о классе Sys.UI.DomEvent.

Класс Sys.UI.DomElement содержит члены, которые позволяют добавлять, удалять и включать или выключать ассоциации класса CSS для клиентских элементов управления и элементов. Эти члены также обеспечивают стандартизированный доступ к свойствам элемента DOM. Дополнительные сведения см. в разделе Класс Sys.UI.DomElement.

Показ: