作者:Dflying Chen ( )
了解了基本概念并完成了预先需求后(请参考:),我们可以开始了开发这个ValidateUserNameExtender了。
首先,在Visual Studio中新建一个Atlas Control Project,我们给它取名为ValidateUserName。在新建以后,解决方案应该如下图所示:
可以看到,Project Template中自动为我们引用了如下程序集:
- Microsoft.Web.Atlas.dll,这是Atlas的核心程序集,将被下面的Microsoft.AtlasControlExtender.dll用到。
- Microsoft.AtlasControlExtender.dll,这是Microsoft为我们提供的Atlas中Extender的基类所在的程序集,我们自定义的Extender中的几个必须Class都继承于这个程序集中提供的基类。
同时,这个Project Template还为我们创建了一个JavaScript文件以及三个C#文件:
- ValidateUserNameBehavior.js,这是我们的Extender中的核心部分,也是容纳一切客户端脚本的文件,其中的内容将基本等同于中的ValidateUserNameBehavior.js文件内容,稍后会有详细分析。Atlas的Extender实际上就是对这个客户端Behavior的封装,使其成为服务器端控件,以简化网站程序开发人员在使用时的工作。而作为控件开发人员,却增加了不少工作。
- ValidateUserNameDesigner.cs,这里用来书写在Visual Studio中提供设计期支持的代码。
- ValidateUserNameExtender.cs,这里用来定义我们的Extender。
- ValidateUserNameProperties.cs,这里用来定义我们的Extender中所用到的属性,这些属性的值将被映射到客户端Behavior的属性上。
让我们先从ValidateUserNameBehavior.js 这个JavaScript文件开始,打开ValidateUserNameBehavior.js文件,我们会发现Template已经为我们添加了77行代码,并且在代码中有好多TODO,在代码的头部read me部分还有3个step:
- 创建局部变量用来存储属性值。
- 将这些局部变量加入到Type Descriptor中,这一步是为了让Atlas了解你的类。
- 为局部变量加上访问器(getter和setter)。
在开始step 1之前,我们先把Template中默认的命名空间改称我们需要的,这里我用的是Dflying.Atlas.ControlTookit.ValidateUserName,并更新所有在代码中出现的相关类名。
然后对于step 1和step 3,我们放在一起做,参考中的ValidateUserNameBehavior.js,应该加入CheckResultLabelID,ServiceName,MethodName,ValidMessage以及InvalidMessage五个属性,这里我只举出一个例子:
var _MethodName; this .get_MethodName = function () { return _MethodName;} this .set_MethodName = function (value) { if (_MethodName != value) { _MethodName = value; this.raisePropertyChanged('MethodName'); }}
然后是step 2 :
this .getDescriptor = function () { var td = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'getDescriptor'); td.addProperty('CheckResultLabelID', String); td.addProperty('ServiceName', String); td.addProperty('MethodName', String); td.addProperty('ValidMessage', String); td.addProperty('InvalidMessage', String); return td;} 最后是构造函数与析够函数,同样出现在TODO 中:
this .initialize = function () { Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'initialize'); _blurHandler = Function.createDelegate(this, blurHandler); this.control.element.attachEvent('onblur', _blurHandler); } this .dispose = function () { if (_blurHandler) { this.control.element.detachEvent('onblur', _blurHandler); _blurHandler = null; } Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'dispose');} 再加上调用Web Service 的Handler 以及相应的CallBack :
this .initialize = function () { Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod( this , 'initialize'); _blurHandler = Function.createDelegate( this , blurHandler); this .control.element.attachEvent('onblur', _blurHandler); } this .dispose = function () { if (_blurHandler) { this .control.element.detachEvent('onblur', _blurHandler); _blurHandler = null ; } Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod( this , 'dispose');} 还有一部分Template 自动生成的Code ,用来连接服务器端与客户端的状态交互,在这个示例中我们不需要使用它,当然,留着也没什么坏处:
this .getClientState = function () { var value = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'get_ClientState'); if (value == '') value = null; return value;} this .setClientState = function (value) { return Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'set_ClientState',[value]); } 最后要注意的是该JavaScript 的最后一行:
Sys.TypeDescriptor.addType('dflying', 'ValidateUserNameBehavior', Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior); 其中dflying 代表我们的Extender 产生的客户端控件声明的前缀,ValidateUserNameBehavior 代表客户端控件的标记名称,这两个名字要取好并记牢,在接下来的CS 文件中也会用到。
这样,完整的ValidateUserNameBehavior.js源代码如下:
ValidateUserNameBehavior.js // (c) Copyright Microsoft Corporation.// This source is subject to the Microsoft Permissive License.// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.// All other rights reserved.Type.registerNamespace('Dflying.Atlas.ControlTookit.ValidateUserName');Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior = function() { Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.initializeBase(this); var _blurHandler; var _CheckResultLabelID; var _checkResultLabel; var _ServiceName; var _MethodName; var _ValidMessage = "You can use this user name."; var _InvalidMessage = "This user name has already been used, please choose another."; this.get_CheckResultLabelID = function() { return _CheckResultLabelID; } this.set_CheckResultLabelID = function(value) { if (_CheckResultLabelID != value) { _checkResultLabel = $(value);debug.assert(_checkResultLabel != null, "CheckResultLabelID must be set to a valid DOM element."); _CheckResultLabelID = value; this.raisePropertyChanged('CheckResultLabelID'); } } this.get_ServiceName = function() { return _ServiceName; } this.set_ServiceName = function(value) { if (_ServiceName != value) { _ServiceName = value; this.raisePropertyChanged('ServiceName'); } } this.get_MethodName = function() { return _MethodName; } this.set_MethodName = function(value) { if (_MethodName != value) { _MethodName = value; this.raisePropertyChanged('MethodName'); } } this.get_ValidMessage = function() { return _ValidMessage; } this.set_ValidMessage = function(value) { if (_ValidMessage != value) { _ValidMessage = value; this.raisePropertyChanged('ValidMessage'); } } this.get_InvalidMessage = function() { return _InvalidMessage; } this.set_InvalidMessage = function(value) { if (_InvalidMessage != value) { _InvalidMessage = value; this.raisePropertyChanged('InvalidMessage'); } } this.initialize = function() { Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'initialize'); _blurHandler = Function.createDelegate(this, blurHandler); this.control.element.attachEvent('onblur', _blurHandler); } this.dispose = function() { if (_blurHandler) { this.control.element.detachEvent('onblur', _blurHandler); _blurHandler = null; } Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'dispose'); } this.getDescriptor = function() { var td = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'getDescriptor'); td.addProperty('CheckResultLabelID', String); td.addProperty('ServiceName', String); td.addProperty('MethodName', String); td.addProperty('ValidMessage', String); td.addProperty('InvalidMessage', String); return td; } function blurHandler() { if (this.control.element.value == '') { _checkResultLabel.innerHTML = ''; return; } Sys.Net.ServiceMethod.invoke( _ServiceName, _MethodName, '', { userNameCandidate : this.control.element.value}, _onMethodComplete ); } function _onMethodComplete(result) { _checkResultLabel.innerHTML = result ? _ValidMessage : _InvalidMessage; } this.getClientState = function() { var value = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'get_ClientState'); if (value == '') value = null; return value; } this.setClientState = function(value) { return Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'set_ClientState',[value]); }}Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.registerSealedClass('Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior', Microsoft.AtlasControlExtender.BehaviorBase);Sys.TypeDescriptor.addType('dflying', 'ValidateUserNameBehavior', Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior); 值此为止,客户端部分已经完成,接下来是服务器端,也就是还剩下的那三个CS文件的编写。
(待续……)
转载于:https://www.cnblogs.com/dflying/archive/2006/06/02/Build_Atlas_Server_Side_Extender__Client_Side_Behavior.html