代码改变世界

ASP.NET AJAX客户端编程之旅(六)——来做一个自己的客户端控件

2008-09-11 10:40  T2噬菌体  阅读(4910)  评论(13编辑  收藏  举报

摘要

      通过前面的文章,我们了解了ASP.NET AJAX框架的很多知识。在这一篇文章中,我们来做一个自己的ASP.NET AJAX客户端控件:PasswordValidator。这个控件关联到的DOM元素是一个span或div,并且关联到一个password类型的input标签,当用户在input中输完密码并且这个input失去焦点时,检测用户输入的密码是否合理,如果合理,则给出这个密码的安全程度。

      从这一篇开始,将使用VS2008作为IDE,请朋友们注意。

建立AJAX客户端控件控件的骨架

      在以前的VS2005中,建立AJAX客户端控件需要新建一个js文件,然后手工写入全部代码。而在VS2008中,内置了对AJAX客户端组件的支持,可以直接建立AJAX客户端组件文件,IDE会为其自动生成程序骨架。建立方法如下:

      首先新建一个工程。在VS2008中,直接建立一个ASP.NET Web site就可以,其中已经内置了对ASP.NET AJAX的支持。我的工程名字叫MyAjaxClientControl

      然后我们在Solution Explorer的网站工程右键单击,选择“Add”->“New Item”,在“Web”选项下有一个“AJAX Client Control”,新建一个这种文件就可以了。我的文件名叫PasswordValidator.js。新建好后,文件初始内容如下。

PasswordValidator.js:

 1/// <reference name="MicrosoftAjax.js"/>
 2
 3Type.registerNamespace("MyAjaxClientControl");
 4
 5MyAjaxClientControl.PasswordValidator = function(element)  border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">{
 6    MyAjaxClientControl.PasswordValidator.initializeBase(this, [element]);
 7}

 8
 9MyAjaxClientControl.PasswordValidator.prototype = {
10    initialize: function() {
11        MyAjaxClientControl.PasswordValidator.callBaseMethod(this'initialize');
12        
13        // Add custom initialization here
14    }
,
15    dispose: function() {        
16        //Add custom dispose actions here
17        MyAjaxClientControl.PasswordValidator.callBaseMethod(this'dispose');
18    }

19}

20MyAjaxClientControl.PasswordValidator.registerClass('MyAjaxClientControl.PasswordValidator', Sys.UI.Control);
21
22if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

 

      我们简单分析一下这段代码,通过它了解一下ASP.NET AJAX客户端组件的大体样子。

      首先我们要在头脑中有一个意识,ASP.NET AJAX扩展了JavaScript,使其具有了面向对象特性,所以,一个ASP.NET AJAX客户端组件可以看成是一个类,既然是一个类,当然就有我们熟悉的东西,如命名空间、成员变量、方法、构造函数、析构函数什么的,当然类还可以继承。有了这么一种意识,理解这段代码就简单多了,当然经过扩展的JavaScript写出的类在语法结构上与传统的C#、Java等类的样子很有差别,但是我们一定要将它看成一个类。

      在C#中,写一个类首先要指定命名空间,这里也不例外。Type.registerNamespace("MyAjaxClientControl");就是指定这个类属于MyAjaxClientControl这个命名空间,在这里Type.registerNamespace是固定用法,记住就行了。

      接下来要声明一个类,js中声明类可没有class这个关键词,而是使用function,没错,一个类就是一个function,你觉得难以理解也要理解,在这里就是这样的。

      MyAjaxClientControl.PasswordValidator = function(element) {
            MyAjaxClientControl.PasswordValidator.initializeBase(this, [element]);
      }

      关于这行代码,是类的声明,同时也是构造函数。从这里看出,一般一个控件的构造函数需要一个参数element,其实这就是需要关联到的DOM。因为ASP.NET AJAX控件本身是虚的,只有和具体的DOM关联后才能发挥作用。而构造函数里还调用了父类的初始化函数,这里不必细究。

      再往下就是有个prototype,这里才是最重要的。这个类的一切成员变量和方法都写在里面,等会这里也是我们主要写代码的部分。关于prototype我不多说,想了解的朋友可以去找JavaScript的书看看,不想了解的只要知道这里放类的成员和方法就够了。可以看到,这里已经自动生成了两个方法,一个是初始化,一个是析构函数。一般这两个函数我们原封不动放在那就可以了。

      再往下看,看到MyAjaxClientControl.PasswordValidator.registerClass('MyAjaxClientControl.PasswordValidator', Sys.UI.Control);这一行代码。这段代码的作用是,告诉系统PasswordValidator这个函数要声明成一个类,并且要继承自Sys.UI.Control,一般我们自己写的可视控件都要继承自Sys.UI.Control。要记住NamespaceName.FunctionName.registerClass是把某个function编程类的方法,其中registerClass需要两个基本参数,第一个是这个类的名字,第二个是要继承的父类。其实后面还可以有参数,表明这个类要实现的接口。

      最后一样不用管它,那是框架需要的一行代码。

编写控件

      在正式编写代码前,我们先来简单分析一下。其实所谓编写,就是给这个类的骨架添加合适的成员变量与方法,因为我们是要完成一个类嘛。在摘要中我们介绍了,这个控件是一个密码强度验证控件。所以,我们需要一个输入:用户输入的密码。这个输入我们可以写成一个数据成员。我们还需要一个输出:密码强度提示信息。我们这个空间最终要关联的DOM是一个span或div,所以这个强度信息可以直接显示在其innerHTML中。另外,我们还需要一个方法:验证密码。这个方法在指定文本框失去焦点时被触发,它将分析密码强度,并输出其强度信息。

      分析到这里,我们基本确定了,我们需要一个成员变量:userPassword,它是需要被验证的密码。还需要一个方法:validate,它验证密码强度并输出信息。下面我们来编码。这里注意,为了使得业务逻辑尽量简单,我们仅仅通过密码的长度确定密码强度,我们的业务逻辑是:3个字符以下视为不合法,4-8视为弱,9-12视为中,13以上视为强。在实际应用中,应该还要通过正则表达式,检查密码的组合情况,来确定密码强度。

PasswordValidator.js:

 1/// <reference name="MicrosoftAjax.js"/>
 2
 3Type.registerNamespace("MyAjaxClientControl");
 4
 5MyAjaxClientControl.PasswordValidator = function(element) {
 6    MyAjaxClientControl.PasswordValidator.initializeBase(this, [element]);
 7}

 8
 9MyAjaxClientControl.PasswordValidator.prototype = {
10
11    _userPassword: null,
12    
13    get_userPassword: function() {
14        return this._userPassword;
15    }
,
16    
17    set_userPassword: function(value) {
18        this._userPassword = value;
19    }
,
20    
21    validate: function() {
22        var tip;
23        var passwordLength = this.get_userPassword().length;
24        
25        if(passwordLength <= 3{
26            tip = "<font color=\"#FF0000\">密码不合法,长度太短</font>";
27        }

28        else if(4 <= passwordLength &&  passwordLength <= 8{
29            tip = "<font color=\"#666600\">密码强度-弱</font>";
30        }

31        else if(9 <= passwordLength && passwordLength <= 12{
32            tip = "<font color=\"#0000FF\">密码强度-中</font>";
33        }

34        else {
35            tip = "<font color=\"#00FF00\">密码强度-强</font>";
36        }

37        
38        this.get_element().innerHTML = tip;
39    }
,
40
41    initialize: function() {
42        MyAjaxClientControl.PasswordValidator.callBaseMethod(this'initialize');
43        
44        // Add custom initialization here
45    }
,
46    dispose: function() {        
47        //Add custom dispose actions here
48        MyAjaxClientControl.PasswordValidator.callBaseMethod(this'dispose');
49    }

50}

51MyAjaxClientControl.PasswordValidator.registerClass('MyAjaxClientControl.PasswordValidator', Sys.UI.Control);
52
53if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

 

      上面就是编写好的控件。我们看到,我们和ASP.N ET AJAX默认一样,使用了JOSN的格式,即定义成员变量时是“变量名:初始值”的格式,我们定义了一个_userPassword变量。然后,我们定义了这个变量的get和set方法,这里注意,我们一定要遵循ASP.NET AJAX规定的格式,即“get_变量名”和“set_变量名”的格式。最后定义了validator方法。

应用控件

      目前,我们只是编写了控件,但是还没有将它应用于实际程序里。我们知道,控件不能独立存在,只能应用于程序才能看到其效果。 

      首先,我们在Default.aspx页面上增加一个密码类型文本框和一个div,而这个div将显示密码强度验证的结果。其代码很简单。如下所示:

Default.aspx:

 1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="MyAjaxClientControl._Default" %>
 2
 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4
 5<html xmlns="http://www.w3.org/1999/xhtml" >
 6<head runat="server">
 7    <title>Untitled Page</title>
 8</head>
 9<body>
10    <form id="form1" runat="server">
11    <asp:ScriptManager ID="ScriptManager1" runat="server">
12        <Scripts>
13            <asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" />
14            <asp:ScriptReference Path="~/PasswordValidator.js" />
15            <asp:ScriptReference Path="~/ajax.js" />
16        
</Scripts>
17    </asp:ScriptManager>
18    <div>
19        <input id="pwdUserPassword" name="pwdUserPassword" type="password" />
20        <div id="pwdUserPasswordValid"></div>
21    </div>
22    </form>
23</body>
24</html>

 

      接下来,我们要运用组件编程的思想进行程序设计。新建一个js文件,命名为ajax.js,这个文件将成为程序的控制器。下面先贴出代码再进行分析:

ajax.js:

 1var txtUserPassword;
 2var validUserPassword;
 3
 4Sys.Application.add_init(onPageInit);
 5
 6function onPageInit()
 7{
 8    txtUserPassword=new Sys.Preview.UI.TextBox($get("pwdUserPassword"));
 9    txtUserPassword.initialize();
10    validUserPassword=new MyAjaxClientControl.PasswordValidator($get("pwdUserPasswordValid"));
11    validUserPassword.initialize();
12    
13    $addHandler($get("pwdUserPassword"),"blur",txtUserPassword_onBlur);
14}

15
16function txtUserPassword_onBlur()
17{
18    validUserPassword.set_userPassword(txtUserPassword.get_text());
19    validUserPassword.validate();
20}

 

      看过前几篇的朋友肯定能很容易理解这短代码。注意其中的validUserPassword被赋予了一个MyAjaxClientControl.PasswordValidator的实例,这正是我们刚才编写的那个控件。而页面如何知道这个控件的存在呢,有没有注意到,在Default.aspx的ScriptManager中,已经引入了PasswordValidator.js文件,这保证了程序可以识别这个自定义控件。我们知道,这个控件的构造函数有一个参数element,是需要关联到的DOM元素,这里我们关联到了pwdUserPasswordValid这个div。

      还要注意的一点就是$addHandler($get("pwdUserPassword"),"blur",txtUserPassword_onBlur);这行代码,由于ASP.NET AJAX的TextBox控件并没有封装on_blur(当控件失去焦点时触发)这个事件,所以我们要在DOM的层面上为这个事件添加监听函数。而$addHandler就是ASP.NET AJAX为我们提供的一种语法缩写,它的原型是$addHandler(DOMElement,eventName,listener),其意思是让listener监听DOMElement的eventName事件,即当DOMElement的eventName被触发时,执行listener函数。具体到这里,就是文本框失去焦点时,执行txtUserPassword_onBlur。

      我们再来看看txtUserPassword_onBlur做了什么:它首先将txtUserPassword的内容赋予validUserPassword的_userPassword变量,然后执行其validate方法。这样,validUserPassword就会对数据进行验证,并将结果显示于指定的div里。

      执行效果看下图:

 

 

      可以看到,随着不同的密码长度,我们自己做的控件给出了相应的密码强度。每次文本框失去焦点时都会进行验证。

结束语

      这一篇中,我们自己做了一个ASP.NET AJAX控件。当然,限于篇幅,不可能将相关的知识全部呈现出来,但是,希望通过做这个控件,可以让广大朋友对ASP.NET AJAX客户端控件的开发有一个初步的认识,也加深对ASP.NET AJAX客户端控件原理的理解。相信只要不断联系,假以时日,朋友们一定可以随心所欲做出自己需要的控件。

      本文示例程序可以在这里下载:MyAjaxClientControl.rar

 

主要参考文献

      [1] 陈黎夫,ASP.NET AJAX程序设计-第II卷:客户端,人民邮电出版社,2007年10月

      [2] ASP. NET AJAX Roadmap Documentation,http://www.asp.net/ajax/documentation/live