ASP.NET AJAX(网页框架、客户端组件开发)

       ASP.NET AJAX 客户端库使用多层设计。最底层是一组允许面向对象模式的 JavaScript 语言增强以及一组对核心 JavaScript 数据类型的扩展。ASP.NET AJAX 还有一组构建在那个框架的核心客户端类和一个客户端页面模型。这个模型包括用于 Web 服务器回调特性的类、用于支持 UpdatePanel 之类的 Web 控件的特定类,以及已经封装页面及其元素的控件类。

1. Application 类

       网页模型的入口点是 Application 类。在浏览器里加载在 ASP.NET AJAX 中可用的 Web 页面之后,就会创建 Sys.Application 类的一个实例

       Application 对象管理页面的组件并加载所有由 ScriptManager 注册的外部脚本文件

       ScriptManager 插入创建 Application 对象的代码,Application 对象为服务器端的 ScriptManager 完成全部客户端工作

       Application 对象引发两个主要事件。load 事件在页面第一次被处理以及每次回发(包括异步回发)后发生。unload 事件在用户离开当前页面打开新页面时发生要处理这些事件,只需添加下面所示名称的 JavaScript 函数即可:

function pageLoad() {
    alert("Begin loaded");
}
function pageUnload() {
    alert("Begin unloaded");
}

       Application 类还提供了一个 init 事件,它在所有脚本都已经被加载但对象还没有创建时发生。init 事件只在页面第一次被处理时发生一次。异步回发后不会发生。通过如下代码可以将事件处理程序附加到 init 事件上:

Sys.Application.add_init(ShowInit);

2. PageRequestManager 类

       另一个同样很重要的类就是 PageRequestManager 。如果页面支持局部呈现,并在服务器端使用了一个或多个 UpdatePanel 控件,PageRequestManager 类就会被创建。PageRequestManager 类引发一组事件,你可以在客户端 JavaScript 代码里响应它们。

PageRequestManager 事件表

initializeRequest 异步回发开始前发生。此时,可通过传送到事件处理程序的 Sys.WebForms.InitializeRequestEventArgs 对象的 Cancel 属性取消回发
beginRequest 在异步回发请求发送前发生,但在 initializeRequest 之后。此时,可初始化页面的等候指示器等工作。该事件提供一个 Sys.WebForms.BeginRequestEventArgs 对象,通过它可以确定是哪一个元素引发了回发
pageLoading 在异步回发请求接收到响应之后但页面被更新前发生。此时,可移除等候指示器。该事件提供一个 Sys.WebForms.PageLoadingEventArgs 对象,它提供作为异步回发响应结果的要更新的面板信息
pageLoaded 在异步回发请求接收到响应之后且页面被更新后发生。该事件提供一个 Sys.WebForms.PageLoadedEventArgs 对象,它详细描述哪些面板已被更新和创建
endRequest 在异步响应被处理后(在 pageLoaded 事件之后)或在处理响应过程中(发生错误时)发生。可以在这时候检查错误并提供定制的错误通知。该事件提供一个 Sys.WebForms.EndRequestEventArgs 对象,详细描述发生的错误

3. 客户端 AJAX 控件

       欲详细了解完整的网页框架技术,可以参考下面地址:

http://msdn.microsoft.com/library/bb398822.aspx

       这一部分,我打算介绍一个来自 ASP.NET AJAX 文档的示例:一个鼠标滑过时会更新自己外观的按钮。为了便于阻止,这个按钮的所有代码被放在 JavaScript 文件 HoverButton.js 中。

       通过之前介绍过的原型模式创建这个控件。注册命名空间、定义控件的构造函数、然后使用 protoType 属性定义公共接口。在这个示例中,类的名字是 HoverButton,它公开按钮被单击、鼠标滑过、鼠标移出时触发的事件。

       这是代码的大体结构:

Type.registerNamespace("CustomControls");
 
CustomControls.HoverButton = function (element) {
    CustomControls.HoverButton.initializeBase(this, [element]);
    this._clickDelegate = null;
    this._hoverDelegate = null;
    this._unhoverDelegate = null;
}
 
CustomControls.HoverButton.prototype = { ... }
 
CustomControls.HoverButton.registerClass("CustomControls.HoverButton",Sys.UI.Control);

       自定义控件的构造函数在开始时必须调用 initializeBase() ,它触发 Control 基类的构造函数!

       原型包含获取和设置按钮文本以及 3 个事件附加处理程序的方法。ASP.NET AJAX 所包含的事件模型比单纯的 JavaScript 要高级。这个事件模型的一个优势是能处理浏览器兼容问题。

       使用 addHandler() 和 removeHandler() 方法在 JavaScript 里注册和解除事件处理程序。下面是实现的大致代码:

CustomControls.HoverButton.prototype = {
    get_text: function () {
        return this.get_element().innerHTML;
    },
    set_text: function (value) {
        this.get_element().innerHTML = value;
    },
 
    add_click: function (handler) {
        this.get_events().addHandler("click", handler);
    },
    remove_click: function (handler) {
        this.get_events().removeHandler("click", handler);
    },
 
    add_hover:function(){ ...},
    remove_hover:function(){ ... }
    ...
 
    initialize:function(){ ... },
    dispose:function(){ ... },
 
    ...
}

       HoverButton 类的原型里还有两个方法:initialize() 方法(它在创建 HoverButton 对象时被自动调用)以及一个对象被释放时所调用的 dispose() 方法

       initialize() 方法建立 HoverButton 类中定义的自定义事件与页面 JavaScript 事件间的链接。例如,下面这段代码建立 hover 事件,这样当鼠标在按钮上移动或按钮获得焦点时它就会发生:

var element = this.get_element();
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);

       _hoverHandler 代理定义在原型的最后。它只是触发关联的事件处理程序:

_hoverHandler: function(event) {
    var h = this.get_events().getHandler('hover');
    if(h){
        h(this,Sys.EventArgs.Empty);
    }
}

       最后,initialize() 方法调用 Control 类中的基方法 initialize();

CustomControls.HoverButton.callBaseMethod(this,"initialize");

       dispose() 方法的任务比较简单。它只检查是否有事件处理程序,如果存在就移除它们。它为 hover 事件做这些事情:

var element = this.get_element();
if (this._hoverDelegate) {
    Sys.UI.DomEvent.removeHandler(element, 'hover', this._hoverDelegate);
    delete this._hoverDelegate;
}

       它使用下面代码调用 dispose() 方法的基类实现结束:

CustomControls.HoverButton.callBaseMethod(this, 'dispose');

       下面给出上述的完整代码,有兴趣的朋友可以仔细阅读一下:

Type.registerNamespace("CustomControls");
 
// Constructor
CustomControls.HoverButton = function (element) {
    CustomControls.HoverButton.initializeBase(this, [element]);
    this._clickDelegate = null;
    this._hoverDelegate = null;
    this._unhoverDelegate = null;
}
 
CustomControls.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;
        }
 
        CustomControls.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);
 
        CustomControls.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);
    }
}
CustomControls.HoverButton.registerClass('CustomControls.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();

       现在就可以在页面中使用它了。首先要把自己的脚本注册到 ScriptManager,如下所示:

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/HoverButton.js" />
    </Scripts>
</asp:ScriptManager>

       这保证了代码在 ASP.NET AJAX 客户端库之后被加载,并且能够完全访问客户端模型。这里只用一个最普通的按钮进行测试即可:

<button type="button" id="Button1" value="Click Me"></button>

       最后,要创建客户端控件并关联事件处理程序。在页面第一次加载时,可以使用 ASP.NET AJAX $create 假名(它触发 Sys.UI.Component.create() 方法)创建控件。此时,需要提供控件的完全限定类名、其他要设置的属性(如文本、样式、事件处理程序)以及页面底层对象的引用(可以通过 $get 假名获得)。

       这是创建 HoverButton、设置控件的初始属性、为 hover 事件附加处理程序的代码:

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

       通过调用 $create 注册某个组件之后,你可以随时使用 $find 获取对它的引用。这个事件处理程序在鼠标滑过按钮时改变它的文本:

function doSomethingOnHover(sender, args) {
    hoverMessage = "The mouse is over the button."
    $get('HoverLabel').innerHTML = hoverMessage;
    $find('Button1').set_text(hoverMessage);
}

       知道 $find 和 $get 之间的区别非常重要。$get 假名获取页面的 HTML 元素(如<button>)。$find 假名获取一个完整的 ASP.NET AJAX 客户端组件(如 HoverButton 对象)。显然,要和自定义控件里的属性交互,就必须使用 $find 获取控件对象。

       下面是页面测试类的所有代码,不包括样式代码:

<asp:ScriptManager runat="server" ID="ScriptManager1">
    <Scripts>
        <asp:ScriptReference Path="HoverButton.js" />
    </Scripts>
</asp:ScriptManager>
<script type="text/javascript">
   1:  

   2:  

   3:     function pageLoad(sender, args) {

   4:         $create(CustomControls.HoverButton,

   5:             { text: 'A HoverButton Control',

   6:                 element: { style: { fontWeight: "bold", borderWidth: "2px"} }

   7:             },

   8:             { click: start, hover: doSomethingOnHover, unhover: doSomethingOnUnHover },

   9:             null, $get('Button1'));

  10:     }

  11:  

  12:     function doSomethingOnHover(sender, args) {

  13:         hoverMessage = "The mouse is over the button."

  14:         $get('HoverLabel').innerHTML = hoverMessage;

  15:         $find('Button1').set_text(hoverMessage);

  16:     }

  17:  

  18:     function doSomethingOnUnHover(sender, args) {

  19:         $get('HoverLabel').innerHTML = "";

  20:     }

  21:  

  22:     function start(sender, args) {

  23:         alert("The start function handled the HoverButton click event.");

  24:     }
</script>
<button type="button" id="Button1"></button>
<div id="HoverLabel"></div>

       测试效果:

image image

       创建客户端 ASP.NET AJAX 组件并不简单。虽然没有任何高层次的复杂度,但有很多细节要管理,松散类型 JavaScript 语言有限的错误捕获能力可能使调试变得一团混乱。

       由于这些原因,大多数的 ASP.NET 开发人员倾向使用现成的服务器端控件以及那些已经提供了 ASP.NET AJAX 特性的组件,而不是自己开发。

原文地址:https://www.cnblogs.com/SkySoot/p/2851452.html