======================================================
注:本文源代码点此下载
======================================================
原文地址:http://sharethispoint.com/archive/2006/11/15/build-web-parts-with-ajax.aspx
如何在开发web部件时使用ajax呢?我们将以一个样子类似moss 2007中kpi和bdc web部件的webpart为例来说明。如果你对ajax一点都不了解,推荐学习terrylee的ajax入门系列。
asp.net2.0有一个很酷的新特性叫作客户端脚本回调。脚本回调主要使我们可以使用javascript调用服务器端程序中的方法,然后根据结果来做一些操作。这就使我们可以动态更新页面的某一部分内容,正如将在我们下面的webpart中看到的,而不必刷新整页。关于在.net2.0中使用客户端脚本回调,可以参考下面的文章地址(http://msdn.microsoft.com/msdnmag/issues/04/08/cuttingedge/),其中做出了详细的解释。但是如何确切的将其使用与我们的代码中,文章并没有详细介绍。事实上脚本回调特性是集成到.net中的,我们可以方便的拿来使用。
本示例中我们假设有这么一个webpart,它需要很长的时间才能显示出内容。为了解决这个问题,给用户更好的体验,我们决定让render方法在webpart刚刚载入时只输出一个空的div标签,然后我们通过ajax来替换div的内容,使其显示出实际需要的内容。这样,用户就可以在页面载入后在我们的webpart完成内容载入前先看一看其他的内容。
下面我们就开始。
首先我们先创建一个新的webpart项目。在我们的webpart类中添加下面的命名空间。
using system.web.ui;
using system.web.ui.webcontrols;
using system.web.ui.webcontrols.webparts;
想要使.net知道我们的类要使用脚本回调,必须实现system.web.ui.icallbackeventhandler接口。
public class treeviewrollup:webpart,icallbackeventhandler
icallbackeventhandler接口有两个方法,public string getcallbackresult()和 public void raisecallbackevent(string eventargs),稍后将对其进行介绍。
我们先定义两个变量
private string datadiv; //用于保存div标签名称
private string ajaxdata; //用于保存ajax返回的数据
datadiv变量保存了html中的我们打算输出内容的div标签的id。这个div标签的名称在一个webpart实例中必须唯一。如果始终是一个固定名称,那么当我们在一个页面中有两个webpart的实例时它们有可能会替换对方的内容。
在webpart的rendercontents方法中加入下面的代码:
protected override void rendercontents(htmltextwriter writer)
{
this.datadiv = this.clientid + "content";//使用webpart实例的客户端id 加上一个给定的名称
writer.write("
"" + this.datadiv + "\">"/_layouts/images/gears_an.gif\" width\"150\">
");
}
我们在最后一行的div标签中加了一个进度条的小gif图。这里直接用了wssv3中的图片。
在onload中粘贴如下代码:
protected override void onload(eventargs e)
{
this.datadiv = this.clientid + "content";
string js = page.clientscript.getcallbackeventreference(this, "'blah'", "filldiv", "'" + this.datadiv + "'", true);
string contentloader= "var ajaxcommands='';window.onload = ajaxloader; function ajaxloader() { eval(ajaxcommands); } function filldiv(arg, ctx){ var mydiv = document.getelementbyid(ctx); mydiv.innerhtml = arg;}";
if (page.clientscript.isclientscriptblockregistered("contentloader") == false)
page.clientscript.registerclientscriptblock(page.clientscript.gettype(), "contentloader", contentloader, true);
page.clientscript.registerstartupscript(this.gettype(), "myloader"+this.clientid, " ajaxcommands = ajaxcommands + \"" + js + ";\";", true);//使用webpart实例的客户端id 加上一个给定的名称作为脚本的key
base.onload(e);
}
在该方法中注册有两块不同的javascript块 。
第一个字符串js的值来源于getcallbackeventreference。getcallbackeventreference方法用于返回执行回调服务器获取数据的javascript。我们传递了:一个当前控件(webpart)的引用;“blah”,作为初始数据当回调启动后将被传递到我们的服务器端组件;当回调结束后调用的javascript方法的名字;我们的标记内容的div标签的名字;异步开关设为true这些必要的参数。
通过该方法生成的javascript类似于下面的样子:
webform_docallback('ctl00$m$g_a010b3bd_1a68_40f9_b46b_f87050cf516f','blah',filldiv,'ctl00_m_g_a010b3bd_1a68_40f9_b46b_f87050cf516fcontents',null,true);
我们可以将这段javascript用于一个button的onclick事件来启动回调并填充div标签。
在本例中,我们不希望用户还要点击什么的才能继续webpart的载入。所以我们要在浏览器载入页面时调用webform_docallback 方法。这是用contentloader字符串来实现的。contentloader字符串定义了一个javascript变量, ajaxcommands,用来保存我们准备执行的一些命令。同时,我们设置window.onload事件使其执行ajaxloader方法。当ajaxloader方法运行时将通过eval函数执行所有存在ajaxcommands变量中的命令。
为什么这么写呢?这是因为如果我们在一个页面里有多于两个的ajax webpart的实例时,每个实例都将会通过window.onload事件来载入数据,这样问题就产生了。只有最后设定的事件处理(event handler)会被执行,并不是所有的设定都执行。为此,我们打了一个擦边球。在window.onload里设定了一个command方法。每一个webpart仅仅扩充其webform_docallback到ajaxcommands 变量。这样,起码解决了本例中的问题。应该算得上一个好办法吧。
最后,contentloader字符串也包括了filldiv方法,用于设定div中的回调所返回的html内容。
最后一步,在我们的类的onload 方法中将脚本注册到页面中。我们只需要在一个页面里有一个contentloader javascript脚本。所以,我们在注册前先判断是否已经被页面中其他的webpart通过脚本管理器注册了。
剩下的事儿就是实现icallbackeventhandler接口所需要的两个方法。
string icallbackeventhandler.getcallbackresult()
{
return this.ajaxdata;
}
void icallbackeventhandler.raisecallbackevent(string eventargument)
{
this.ajaxdata="some crazy message here!
"+this.clientid;
}
raisecallbackevent当客户端回调启动时将被调用。它是一个无返回值的方法,仅用于将getcallbackresult方法需要的数据准备好。raisecallbackevent方法是我们放置所有用于返回给webpart的render方法要显示内容的相关代码的地方。本例中我们只发送一条简单的信息给客户端。为了区分不同的webpart实例确实做了各自的工作,我们在信息后加上了各自的clientid
赶快动手实践一下吧,希望大家对使用客户端回调已经入门了。
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/