创建自定义 AJAX 客户端控件

来源:百度文库 编辑:神马文学网 时间:2024/04/20 17:17:20
创建自定义 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 元素。

  • 封装要跨应用程序重用的客户端代码。

行为

  • 从扩展 Component 基类的 Behavior 基类派生。

  • 扩展 DOM 元素的行为,例如,可附加到现有文本框的水印行为。

  • 可以创建 UI 元素,尽管它们通常不会修改附加到关联 DOM 元素的标记。

  • 如果分配了 ID,则可以通过自定义属性 (expando) 直接从 DOM 元素访问。

  • 不需要与其他客户端对象(例如,从 ControlBehavior 类派生的类)关联。

  • 可以在其 element 属性中引用控件或非控件 HTML 元素。

控件

  • 从扩展 Component 基类的 Control 基类派生。

  • 表示作为客户端对象的 DOM 元素,通常会更改原始 DOM 元素的一般行为以提供新功能。例如,菜单控件可能会从 ul 元素读取 li 项作为其源数据,但不显示项目符号列表。

  • 可通过控件 expando 直接从 DOM 元素访问。

 先决条件

若要运行本主题中提供的客户端控件示例,您需要:

  • 一个支持 AJAX 的 ASP.NET 网站。如果您已配置了这样的站点,则可以在本示例中使用该站点。有关如何创建虚拟目录或站点的更多信息,请参见如何:在 IIS 5.0 和 6.0 中创建和配置虚拟目录

 创建自定义 ASP.NET AJAX 客户端控件的基本功能

ASP.NET AJAX 客户端控件将 DOM 元素表示为客户端对象,并扩展该元素的标记表示形式或为该元素提供附加功能。例如,客户端控件可通过应用不同的 CSS 样式来扩展 HTML 元素,以响应鼠标事件。

客户端控件封装要跨应用程序重用的 JavaScript 代码。通过从 Control 基类派生,自定义控件自动继承许多内置跨浏览器功能,其中包括:

  • 为与控件关联的 DOM 元素和控件本身的事件处理程序添加和移除事件处理程序的功能。

  • 自动将控件注册为可释放的对象,该对象实现 Sys.IDisposable 接口。

  • 在属性发生更改时引发通知事件的功能。

  • 对控件属性设置执行批处理的功能。与在各个属性 get 和 set 访问器中处理所有逻辑相比,此操作在脚本大小和处理时间上更有效。

 实现客户端控件

下表总结了实现从 Control 派生的自定义客户端控件的步骤。有关每个步骤的更多详细信息在表后介绍。

步骤

摘要

使用原型设计模式定义客户端控件类。

  1. 注册控件类的命名空间。

  2. 定义控件的构造函数以接收 DOM 元素参数,并定义原型。

  3. 将控件函数注册为从 Control 基类派生的类。

初始化控件的基 Control 实例,并将关联的 DOM 元素作为参数传递。

  • 在控件的构造函数中,调用它的继承 Type.initializeBase 方法,并将在构造函数参数中接收的 DOM 元素传递给该基实例。

公开所有属性访问器,并可以选择是否引发 Sys.Component.propertyChanged 通知事件。

  • 使用 get 和 set 访问器方法公开组件原型中的属性。

  • 如果对于任何属性的更改,发出通知非常重要,请从属性的 set 访问器引发 propertyChanged 通知事件。

重写 Sys.UI.Control.initialize 方法以初始化任何属性和事件侦听器。

如果组件或 DOM 元素有任何属性或事件侦听器要初始化,请重写组件原型中的 initialize 方法。在重写的方法中执行以下操作:

  • 通过调用 Sys.UI.DomEvent.addHandler 方法,将任何委托添加到 window 对象或某个元素的 DOM 事件。

  • 设置任何初始 DOM 元素属性。

  • 设置任何辅助功能属性 (property),如 DOM 元素的选项卡索引或控件的 role 属性 (attribute)。

  • 调用基类的 initialize 方法。

重写 Sys.UI.Control.dispose 方法以释放资源,如移除 DOM 事件处理程序。

如果在释放控件之前有任何要释放的资源,请重写组件原型中的 dispose 方法。在重写的方法中执行以下操作:

  • 停止控件可能进行内部排队的任何进程,并禁用已公开给调用方的任何功能。

  • 在释放控件之前移除 DOM 事件处理程序。通过清除由您的控件设置的任何 DOM 元素处理程序,可以移除对那些 DOM 元素的任何循环引用,并释放为那些元素保留的内存。

  • 调用基 dispose 方法。dispose 方法中的所有代码必须是可多次调用的。例如,在您尝试释放一项资源之前,请验证该资源尚未被释放。

使用原型设计模式定义控件类

ASP.NET AJAX 客户端类(其中包含一个控件类)是使用原型设计模式通过 JavaScript 定义的。有关详细信息,请参见使用原型模型创建客户端组件类

客户端控件类必须从 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 网页中使用自定义客户端控件,请执行以下操作:

  • 在网页中注册客户端控件的脚本库。

  • 创建客户端控件实例。

以下各节提供了有关这些步骤的详细信息。

在网页中注册控件的脚本库

可以以声明方式或编程方式向 ScriptManager 控件注册页面上客户端控件所需的脚本。

下面的示例演示注册控件脚本的 ScriptManager 控件的声明性标记。

复制代码

asp:ScriptManager 元素在 scripts 节点内包含 asp:ScriptReference 元素。asp:ScriptReference 元素的 path 属性引用定义控件类的 HoverButton.js 文件的路径。有关更多信息,请参见动态分配脚本引用ScriptManager 类概述。

说明:

若要向 ScriptManager 控件注册的所有独立脚本文件必须调用 notifyScriptLoaded 方法以通知应用程序,脚本已完成加载。嵌入到程序集中的脚本在大多数情况下不应调用此方法。有关更多信息,请参见 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 控件

在本节中,将创建一个名为 HoverButton 的简单的自定义客户端控件,该控件扩展 Control 基类,然后在页面中使用该控件。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 实例作为可释放的对象注册到客户端应用程序。

在原型中,代码声明公共事件 clickhoverunhover。网页开发人员可以添加和移除侦听这些事件的处理程序。这些方法又转而通过控件的事件处理程序集合来添加或移除指定的处理程序。可以通过控件的 Sys.EventHandlerList 对象添加和移除控件类中的处理程序。EventHandlerList 对象通过继承的 Sys.Component.events 属性包含控件的事件处理程序的集合。在示例中,代码调用返回的 EventHandlerList 对象的 Sys.EventHandlerList.addHandlerSys.EventHandlerList.removeHandler 方法,以添加或移除处理程序。

HoverButton 类重写基 dispose 方法,以在释放控件之前安全地释放任何控件资源(如 DOM 事件的处理程序)。最后,代码调用基 dispose 方法以使应用程序释放控件。

 在网页中使用 HoverButton 控件

在本节中,您将学习如何在网页中使用客户端脚本创建控件实例。

创建使用 HoverButton 控件的网页

  1. 在您保存 HoverButton.js 文件的应用程序根目录下,创建一个名为 DemoHoverButton.aspx 的文件。

  2. 将以下标记和代码添加到该文件中:

    复制代码
                    Control Demo            
    <asp:ScriptManager runat="server" ID="ScriptManager01"> <asp:ScriptReference Path="HoverButton.js" /> asp:ScriptManager>  

代码讨论

DemoHoverButton.aspx 文件是该自定义控件所在的 ASP.NET 网页。在该页中,绑定到自定义控件的函数在 script 元素中定义。在 Sys.Application.init 事件处理程序中,将通过调用 $create 方法在客户端脚本中实例化 HoverButton 控件。该代码将以下参数传递给 $create 方法:

  • type 参数包含您先前创建的 Demo.HoverButton 类。

  • properties 参数包含一个 JSON 对象,该对象包含所需的控件 ID 值,后跟使用初始值指定属性名称的属性名称/值对。

  • events 参数包含一个对象,该对象包含与事件处理程序配对的事件名称。

ScriptManager 控件中,asp:ScriptReference 节点的 path 属性引用定义 Demo.HoverButton 控件类的 HoverButton.js 文件的路径。

 设置 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