65.9K
CodeProject 正在变化。 阅读更多。
Home

AJAX 客户端控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.39/5 (9投票s)

2007 年 7 月 24 日

CPOL

6分钟阅读

viewsIcon

68598

downloadIcon

564

本文介绍如何使用 ASP.NET AJAX 库创建客户端控件。

引言

本文介绍了使用新的 AJAX 框架进行客户端控件开发的说明。我附上了一些使用 AJAX 库开发的客户端控件示例。本文是了解 AJAX 客户端组件开发的一个很好的起点。

背景

JavaScript 是一种面向对象的语言,但其方法与其他语言(如 C# 或 C++)截然不同。JavaScript 没有类的概念,因此对象不是类的实例。JavaScript 对象可以被视为键值对的集合。

在 JavaScript 中,对象可以通过多种方式创建。例如:

var table = new Object();
//or
var table = {};

可以向此对象添加属性。

table.Name = "Ikea Comp table";
//or
table["Name"] = "Ikea Comp table";

如果属性之前未定义,则在赋值时会创建它。

同样,可以将函数添加到上述 table 对象中。

table.GetName = function()
{
  return this.Name;
}

在 JavaScript 中创建对象的另一种方法是:

//this function can be represented 
//as a class with properties and functions inside it.

function Cat()
{
    this.name = "kitty"
    this.type = "big";
    this.Details = function ()
    {
        alert(this.name +" " +this.type);
    }
}

//This method is shared within all objects
//Prototype is used to define the template of the object and used 
//to implement inheritance. Reference to objects and arrays added to 
//the prototype object are shared between all the instances. 
//functions defined in prototype are also shared between objects and it 
//saves a little memory but are a little slow to call as compared to 
//functions defined in constructor
//another way to write Cat.prototype.speak = function()....

Cat.prototype={
    speak : function()
    {
    alert('meaaoooww');
    }
}

//Static Function on Cat Object

Cat.StaicFunc = function()
{
    //this.name or any other property is not accessible 
    //because it is a static method

    alert("static function called");
}

//object of class;

var cat = new Cat();    
cat.speak();
cat.Details();
Cat.StaicFunc();
    
Inheitance can be implemented in JavaScript as

function WildCat()
{
    Cat.call(this); //Calling the base constructor
}

WildCat.prototype  = new Cat();
//Overriding the base function speak

WildCat.proptotype.speak = function()
{
    alert('this is wild cat..Beware');
}

创建对象的更快方法是:

var team = {name:'', members:[], count:function() { return members.length }}

上述对象是使用 JSON 格式创建的。要了解更多关于 JSON 格式的信息,请“Google”一下 :-)。

AJAX 库中的 JavaScript

ASP.NET AJAX 库扩展了 JavaScript 类型系统,以模拟 JavaScript 目前尚不具备的面向对象结构,例如接口、类和枚举。类的创建方式与 JavaScript 类似。要在 AJAX 框架中创建类:

Type.registerNamespace('Sample');
Sample.Vehicle = function ()
{
    this._name;
    this._type;
}
Sample.Vehicle.prototype = {
   get_name : function()
   {
        return this._name;
   },
   set_name : function (value)
   {
        this._name = value;
   },
   get_type : function()
   {
        return this._type;
   },
   set_type : function(value)
   {
        this._type = value;
   },
   Honk :  function()
   {
        alert('Loud noise coming...cant you hear that');
   }     
}
Sample.Vehicle.registerClass('Sample.Vehicle');

在上面的示例中,您只需调用 registerNamespaceregisterClass 来向 AJAX 库注册您的命名空间和类。上述类有两个属性和一个函数。应使用 get_set_ 格式来获取和设置属性的值。

registerClass 的格式类似于:

NameofClass.registerClass('NameofClass', BaseClass, InterfacesImplemented)

接口可以定义为:

Sample.IDrive = function()
{
    throw Error.notImplemented();
}
Sample.IDrive.prototype = {
Drive : function ()
    {
        throw Error.notImplemented();
    }
}
Sample.IDrive.registerInterface('Sample.IDrive');

要从上述 Vehicle继承一个类并实现接口:

Sample.Honda = function()
{
    Sample.Vehicle.initializeBase(this);
    //if base class takes arguments in constructor 
    //then they can also be passed

    //Sample.Vehicle.initializeBase(this, [arg1,arg2,...]);

}
Sample.Honda.prototype = {
    Honk: function()
    {
        alert(this._name + ' honking ...');
    //To call base method

        //Sample.Honda.callBaseMethod(this, 'Test',[arg1,arg2,…]);

    } ,
    Drive : function()
    {
        alert('Driving...');
    }
}
Sample.Honda.registerClass('Sample.Honda',Sample.Vehicle, Sample.IDrive);

要添加/移除事件,请使用 add_eventname/remove_eventname。例如:

Sample.List = function() {
    this._items = [];
    this._events = new Sys.EventHandlerList(); 
}
Sample.List.prototype = {
    add : function(item) {
        this._items.push(item);
        this._raiseEvent('itemAdded', Sys.EventArgs.Empty);
    },
    get_events : function() {
        return this._events;
    },
    add_itemAdded : function(handler) {
        this.get_events().addHandler('itemAdded', handler);
    },
    remove_itemAdded : function(handler) {
        this.get_events().removeHandler('itemAdded', handler); 
    },
    _raiseEvent : function(eventName, eventArgs) {
        var handler = this.get_events().getHandler(eventName); 
        if (handler) {
        if (!eventArgs) {
            eventArgs = Sys.EventArgs.Empty;
            }
            handler(this, eventArgs);
        }
    }
}
Sample.List.registerClass('Sample.List');

使用 AJAX Toolkit 创建客户端组件

要开始使用 AJAX,请安装 ASP.NET AJAX toolkit,并创建一个名为“ASP.NET AJAX Enabled Website”的模板网站。

在每个 AJAX 启用的网站中,默认页面上都会有一个 ScriptManager 控件,并且 'Web.config' 文件已配置为支持 AJAX。此 ScriptManager 控件的主要目的是将所有 AJAX 脚本传递给客户端并注册 Web 服务。此控件部署的文件可以是 AJAX toolkit 提供的脚本,也可以是您创建的任何其他脚本文件。

要部署包含 AJAX 类和代码的 JavaScript 文件,请编写:

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

添加对 Web 服务的引用

<asp:ScriptManager ID="ScriptManager1" runat="server" >        
        
<Services>
    <asp:ServiceReference Path="~/Services/Service1.asmx" />
    <asp:ServiceReference Path="~/Services/Service2.asmx" />
</Services>
</asp:ScriptManager>

只需在页面上添加此控件,它就可以声明式地或以编程方式提供脚本。

组件背景

组件是任何应用程序的构建块。它们封装了功能,并允许跨项目重用。我将讨论 AJAX toolkit 库的组件模型,并给出一个示例。AJAX 库允许使用 JavaScript 创建组件。使用 AJAX 创建组件的过程与 .NET Framework 类似。AJAX 组件继承自 Sys.Component 类。

AJAX 组件被归类为:

  1. 可视化组件:它们具有用户界面。它们继承自 BehaviorControl 类。例如:Button,或 TextBox 控件在获得焦点时的行为(本文附有示例)。
  2. 非可视化组件:它们没有任何用户界面。它们继承自 Sys.Component 类。

上图显示了 ComponentControlBehavior 之间的关系。ControlBehavior 之间的区别在于,Behavior 用于增强 Control 的基本功能。例如:如果一个 TextBox 被分配了一个新的 Behavior,它仍然可以接受输入,但我们可以改变 TextBox 在获得焦点时的外观。而 Control 则是用来改变现有控件的功能的,例如:创建一个新的自动更新文本框控件。

创建组件

创建组件需要您重写 Sys.Component 基类的 InitializeDispose 方法。

Type.registerNamespace("Sample");

Sample.TestComponent = function() {
    Sample.TestComponent.initializeBase(this);
    }
    Sample.TestComponent.prototype = {
    //Overide initialize method

    initialize : function() {
        Sample.TestComponent.callBaseMethod(this, 'initialize');
        alert("Initialize called on TestComponent");
    },
    //Overide dispose method

    dispose : function() {
        alert("Dispose called on TestComponent");
        Sample.TestComponent.callBaseMethod(this, 'dispose');
    },
    time : function() {
        var a = new Date();        
        alert(a.getTime());
    }
}
Sample.TestComponent.registerClass('Sample.TestComponent',Sys.Component);

在 ASPX 页面上,添加:

//register pageInit function to be called on initialized stage of the page

Sys.Application.add_init(pageInit);
function pageInit() {
       //creating component 

 //Alias of Sys.Component.create              

        $create(Sample.TestComponent, {'id':'testComponent1'});
}
function pageLoad() {
  //find component and call its methods and properties

  //$find -- Alias of Sys.Application.find

        var testComponent = $find('testComponent1');
        testComponent.time();
}

"Sys.Application" 是库提供的一个运行时对象,用于管理应用程序中注册的客户端组件。"$create" 是 Sys.Component.create 的别名。此方法在后台执行许多任务来创建一个组件。此方法必须在页面初始化阶段调用。使用 $create 在页面上创建的所有组件都成为 Sys.Application 对象的子组件。$findSys.Application.find 的别名,用于获取 Sys.Application 的子组件的引用。$getSys.UI.DomElement.getElementById 的别名,用于获取 DOM 元素的引用。

$create 的完整语法是:

$create(ComponentName, {Dictionary of properties }, 
       { Dictionary of events}, {Dictionary of refrences}, 
         $get(associatedElementID));

对于组件,我们不需要 associatedElementID,但对于 BehaviorControl,这是一个必需的参数。

如果组件是 BehaviorControl,那么 $create 会将其附加到元素 $get(associatedElementID)

$find 的完整语法是:

$find('componentId', container);

默认情况下,所有由 $create 创建的组件都成为 Sys.Application 的子组件,因此如果我们使用 $create 创建一些组件,则无需在 $find 中指定容器,因为默认搜索是在 Sys.Application 下进行的。

$create 执行的工作与以下代码行相同:

var testComponent = new Sample.TestComponent();
            testComponent.set_id('testComponent');
            testComponent.initialize();
            Sys.Application.addComponent(testComponent);

不一定非要在 Sys.Application 下创建组件,但这是一个好习惯。组件可能很复杂,并且可以包含其他对象或子组件,因此对实例进行初始化和处置的集中式位置非常重要。当组件添加到 Sys.Application 容器中时,它会负责初始化和处置组件。它确保在页面加载发生之前初始化所有添加的组件。

我们也可以在 PageLoad 事件中创建上述组件的实例,如下所示:

function pageLoad() {
    var testComponent = new Sample.TestComponent();
    testComponent.time();
}

创建 Behavior

Behavior 继承自 Sys.UI.Behaviour,而 Sys.UI.Behaviour 又继承自 Sys.Component。Behavior 必须提供一个要关联的元素。Behavior 的构造函数接受一个元素,并将该元素传递给基类构造函数。

例如

Type.registerNamespace("Sample");

Sample.TestBehavior = function(element) {
    Sample.TestBehavior.initializeBase(this,[element]);
    }
    Sample.TestBehavior.prototype = {
    //Overide initialize method

    initialize : function() {
        Sample.TestBehavior.callBaseMethod(this, 'initialize');
        alert("Initialize called on TestComponent");
    },
    //Overide dispose method

    dispose : function() {
        alert("Dispose called on TestComponent");
        Sample.TestBehavior.callBaseMethod(this, 'dispose');
    }
}
Sample.TestBehavior.registerClass('Sample.TestBehavior',Sys.UI.Behavior);

上述 Behavior 什么也不做。在调用 $create 时,必须传递一个元素实例,此 Behavior 将应用到该元素。

$create 会是这样的:

$create(BehaviorName, {Dictionary of properties }, 
       { Dictionary of events}, {Dictionary of refrences} , 
         $get(associatedElementID));

$find 会是这样的:

var instance = $find('ElementName$BehaviorName');

创建 Control

Behavior 不同,Control 继承自 Sys.UI.Control,而 Sys.UI.Control 继承自 Sys.Component。Control 的构造函数也接受一个要关联的元素。一个元素只能关联一个 Control。

例如

Type.registerNamespace("Sample");

Sample.TestControl = function(element) {
    Sample.TestControl.initializeBase(this,[element]);
    }
    Sample.TestControl.prototype = {
    //Overide initialize method

    initialize : function() {
        Sample.TestControl.callBaseMethod(this, 'initialize');
        alert("Initialize called on TestComponent");
    },
    //Overide dispose method

    dispose : function() {
        alert("Dispose called on TestComponent");
        Sample.TestControl.callBaseMethod(this, 'dispose');
    }
}
Sample.TestControl.registerClass('Sample.TestControl',Sys.UI.Control);

$create 对于 ControlBehavior 相同。$find 也与 Behavior 的情况相同。我们可以通过在 $find 中传递 ID 来访问 Control。Control 的 ID 不能像 Behavior 那样以编程方式设置。Sys.UI.Control 类会自动为 Control 分配一个 ID,该 ID 与关联元素的 ID 相同。因此,要通过 $find 访问 Control,请传递元素的 ID。

AJAX 启用的服务器控件

我上面解释的控件是客户端控件。这些控件需要在页面生命周期的初始化阶段创建。创建控件的过程由 $create 语句封装,但我们需要手动将 $create 语句注入页面。如果我们能自动添加这个 $create 语句,那么我们就可以拥有一个服务器控件。AJAX 服务器框架提供了脚本描述符,可用于将此语句注入页面代码。

ScriptComponentDescriptor 可用于创建非可视化组件,类似地,ScriptBehaviorDescriptorScriptControlDescriptor 可用于创建 BehaviorControl

在我的下一篇文章中,我将解释 AJAX 启用的服务器控件是如何工作的。

© . All rights reserved.