打造“AJAX”风格的客户端进度条控件

 一、 Asp.net Atlas简介
    2005年9月,ASP.NET小组发布了代号为“Atlas”的ASP.NET中新功能的第一个社区技术预览(CTP)。微软.NET Framework 2.0的这一功能扩展使开发人员能够同时利用浏览器和服务器功能更轻松地创建丰富的交互式网站。
    ASP.NET的Atlas功能不仅是用于编写以客户端为中心的Web应用程序的另一个AJAX脚本库。Atlas基于.NET Framework 2.0构造并为更好地利用客户端JavaScript和XMLHttpRequest对象新增了支持功能。它包括能够更轻松地丰富现有ASP.NET应用程序的基于服务器的功能,以及Atlas控件和服务所使用的客户端脚本库。下图1中的体系结构图显示,Atlas体系结构跨接客户端和服务器,成为创建更丰富、响应更及时的跨浏览器Web应用程序的一组广泛的开发技术。

图1.Atlas体系结构

Atlas框架包含了Microsoft.Web.Atlas.dll装配集,它包含了服务器端托管的和客户端JavaScript API。其中,客户端库包括一组JavaScript文件,它们被打包为Microsoft.Web.Atlas.dll装配集中的一部分资源。
在本文中,我们主要讨论创建一个基本的客户端Atlas进度条控件的关键实现技术,并提供完整的源码实现。
    二、 步骤1:从Web.UI.Control派生
    首先,你要从基Atlas控件类Web.UI.Control中进行派生。它为你完成一些繁重的任务,例如把它自身与HTML元素相关联等。另外,你还应该注册你的类型,这样我们有可能以声明方式来实例化这个控件。在本例子中,我们将使用命名空间“script”和标签名“progressBar”来注册我们的类型。另外,你还应该注册你的类,这样Atlas才能够实现其功能,例如描述基类型是什么,等等。
Web.UI.ProgressBar = function(associatedElement) ...{
Web.UI.ProgressBar.initializeBase(this, [associatedElement]);
}
Type.registerSealedClass('Web.UI.ProgressBar', Web.UI.Control);
Web.TypeDescriptor.addType('script','progressBar', Web.UI.ProgressBar);

    三、 步骤2:使之可配置
    现在,你需要添加一些属性以便让用户能够配置该控件。在我提供的这个例子中,我们将添加这样一些属性:一个时间间隔(interval),指向服务的url,还有一个我们将在这个服务上调用的方法以便获取当前进度。所有属性都必须遵循严格的命名规范:每一个属性的getter应该是一个以“get_”为前缀的函数;而属性的setter应该是以“set_”为前缀,并且只有一个参数。另外,我们还应该把这些属性添加到我们的控件的描述符中。具体情况请参考后面的步骤4。
//定义一个“私有字段” 
var _serviceURL;
this.get_serviceURL = function() ...{
return _serviceURL;
}
this.set_serviceURL = function(value) ...{
_serviceURL = value;
}

    四、 步骤3:添加一个每隔一定时间查询服务的定时器
    既然我们想每隔n毫秒对服务进行查询,所以我们只能内部重用Web.Timer控件。为此,我们应该定义一个代理来描述我们想每隔一定时间调用该计时器的函数。为了安全起见,我们应该确保在释放我们的控件后进行必要的清理工作。
请注意,当我们仍然等待一个响应时,我们要想办法防止我们的控件多次查询服务。
var _responsePending;
var _timer;
var _tickHandler;

this.initialize = function() ...{
Web.UI.ProgressBar.callBaseMethod(this, 'initialize');
_tickHandler = Function.createDelegate(this, this._onTimerTick);
//把我们的事件处理器添加到定时器的tick事件 
_timer.tick.add(_tickHandler);
this.set_progress(0);
}

this.dispose = function() ...{
if (_timer) ...{
//删除定时器的tick事件到我们的事件处理器的引用 
_timer.tick.remove(_tickHandler);
_tickHandler = null;
_timer.dispose();
}

//为了安全起见,我们应该显式地把设置为null
//以确保我们不再引用该计时器 
_timer = null;

Web.UI.ProgressBar.callBaseMethod(this, 'dispose');
}

this._onTimerTick = function(sender, eventArgs) ...{
if (!_responsePending) ...{
_responsePending = true;

//异步地调用服务方法.传递一个到控件的引用作为上下文,这样以来
//我们可以把它应用于我们的“_onMethodComplete”回调函数中 
Web.Net.ServiceMethodRequest.callMethod(_serviceURL, _serviceMethod,
null, _onMethodComplete, null, null, this);
}
}

function _onMethodComplete(result, response, context) ...{
//取得一个到该控件的引用 
var behavior = context;
//更新进度条 
behavior.set_progress(result);
_responsePending = false;
}


    五、 步骤4:添加一些方法以控制我们的进度条
   最后,我们应该添加一些方法以启动或停止我们的进度条。为此,我们仅需要添加函数start和stop,分别用于启动和禁止该计时器。因为我们想从其它对象中调用这两个函数,所以,我们应该在我们的控件的描述符中描述这些方法。
this.getDescriptor = function() ...{
var td = Web.UI.ProgressBar.callBaseMethod(this, 'getDescriptor');
td.addProperty('interval', Number);
td.addProperty('progress', Number);
td.addProperty('serviceURL', String);
td.addProperty('serviceMethod', String);
td.addMethod('start');
td.addMethod('stop');
return td;
}
this.start = function() ...{
_timer.set_enabled(true);
}
this.stop = function() ...{
_timer.set_enabled(false);
}

    六、 步骤5:测试我们的控件
    现在,我们已经实现了控件,接下来就应该对之进行测试。一旦你添加了一个对你的新脚本控件的文件的引用,你就应该能够使用它。由于我们的进度条需要显式地启动,并且因为我们想模拟一个任务,所以,我们应该加入更多的控件来更好的描述这个演示程序。
[...]
<divclass="progressBarContainer="pb1"class="progressBar"></div> 
</div>
[...]

<scripttype="text="http://schemas.microsoft.com/xml-script/2005"> 
<components>
<!—调用这个组件来实际地启动模拟一项消耗时间的任务-->
<serviceMethodid="taskService1="TaskService.asmx" 
methodName="StartTask1"/>

<!—我们的进度条的id应该参考一个有效关联的HTML元素-->
<progressBarid="pb1="500"serviceURL="TaskService.asmx" 
serviceMethod="GetProgressTask1"/>

<!—我们创建的按钮应该既能启动任务也能启动进度条-->
<buttonid="start1="taskService1"method="invoke"/> 
<invokeMethodtarget="pb1="start"/> 
</click>
</button>
</components>
<references>
<addsrc="ScriptLibrary="ScriptLibrary/AtlasControls.js"/> 
<!--添加一个到我们的控件的参考.-->
<addsrc="ScriptLibrary/ProgressBar.js"/>
</references>
</page>
</script>

    在上面的代码中,我们调用一个方法“StartTask1”in我们的服务来启动该任务,然后调用“GetProgressTask1”来获知这项任务的进度。这全依赖于你如何实现这些。例如,如果你有一个文件上载的情况,那么,通过检查有多少字节已经被上传以及该文件多大,你可以实现“GetProgressTask1”。
注意,在这个淙演示程序中,我们不可能让你把任何内容上载到特定的服务器中,所以它选择模拟一个消耗时间的任务来代替。这项任务可以处于“睡眠状态”,并且每隔100/200毫秒注册一下进度。下面的GetProgressTask1方法仅返回该注册的进度。
[WebMethod]
publicint GetProgressTask1()
...{
//取得用户当前运行的任务相应的进度 
string processKey = this.Context.Request.UserHostAddress + "1";
object savedState = this.Context.Cache[processKey];
if (savedState != null)
...{
return (int)savedState;
}
return 0;
}
[WebMethod]
publicvoid StartTask1()
...{
string processKey = this.Context.Request.UserHostAddress + "1";
//创建一个锁对象以防止一个用户多次运行同一个任务 
string threadLockKey = "thread1" + this.Context.Request.UserHostAddress;
object threadLock = this.Context.Cache[threadLockKey];
if (threadLock == null)
...{
threadLock = newobject();
this.Context.Cache[threadLockKey] = threadLock;
}
//每一位用户只允许一个运行任务 
if (!Monitor.TryEnter(threadLock, 0))
return;
//模仿一种消耗时间的任务 
for (int i = 1; i <= 100; i++)
...{
//相应于该任务更新进度条 
this.Context.Cache[processKey] = i;
Thread.Sleep(100);
}
//任务已经完成,释放锁。 
Monitor.Exit(threadLock);
}


  七、 小结
    Asp.Net Atlas是一个创建基于客户端Web应用程序的框架。这个框架在提供客户端和服务器端API用来创建跨浏览器兼容的AJAX风格的应用程序的同时,还引入了另外一些特征极为丰富的特征。要想基于微软平台开发新一代Web 2.0应用程序,很有必要了解这个框架,而本文提供的小例仅为其“冰山一角”,供参考。

转载:http://tech.it168.com/j/2006-08-28/200608281557036.shtml

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值