用ASP.NET 2.0实现AJAX风格的Web开发(2)
http://www.sina.com.cn 2006年04月13日 15:45
天极yesky
在客户端,为了初始化回调功能,需要调用一个特殊的JavaScript函数。你可以通过调用ClientScriptManager.GetCallbackEventReference来获得一个到这个特殊的JavaScript函数的引用。到GetCallbackEventReference的调用将产生一个回调引用。当调用此回调函数时,你只需要传递一个字符串类型的参数。这是与服务器端的RaiseCallbackEvent签名一致的。这就是你在客户端建立回调机制所需做的一切。其它的把客户端回调函数钩(hook up)到服务器端的IcallBackEventHandler接口的RaiseCallbackEvent方法的实现则是由框架来完成的。前面提到的初始化回调机制的特殊JavaScript函数使用了另外两个参数(__CALLBACKPARAM和__CALLBACKID)作为回馈数据,它们分别代表传递到调用者的字符串参数和控件的ID。在服务器端,ASP.NET检测其它两个参数的存在并且会把请求路由到适当的控件,这将导致调用目标控件上的RaiseCallbackEvent方法。为了解决前面提到的页面上的控件的初始化问题,ASP.NET运行时刻在服务一次回调时提供了一个简化版本的HttpPage生命周期。这一周期包括浏览页面初始化的某个具体阶段,观察状态加载,页面加载和回调函数事件处理等。一旦回调函数事件被控件所处理,HttpPage生命周期的其它阶段就会被跳过。
为了帮助更好地理解ASP.NET 2.0的回调机制,发行包中包括了一个简单的进度条控件,它依靠回调来决定服务器确定的一项任务的状态。下面的列表1显示了该ProgressBar控件的代码。为了支持客户端回调函数,这个控件实现了ICallbackEventHandler接口。为了演示之目的,RaiseCallbackEvent方法实现简单地查找存储在会话中的一个计数器,每次给计数器加1,并且把新值返回到客户端。最后,列表2显示了负责初始化该回调函数的JavaScript代码。它使用了this.Page.ClientScript.GetCallbackEventReference来获得一个到需要初始化回调的函数的安全引用。
列表1:ProgressBar.cs
public class ProgressBar : System.Web.UI.Control, System.Web.UI.ICallbackEventHandler{ private int PercentCompleted{ get { if System.Web.HttpContext.Current.Session["PercentComplete"] == null) { System.Web.HttpContext.Current.Session["PercentComplete"] = 1; } else { System.Web.HttpContext.Current.Session["PercentComplete"] =(int)System.Web.HttpContext.Current.Session["PercentComplete"] + 1; } return (int)System.Web.HttpContext.Current.Session["PercentComplete"]; } set { System.Web.HttpContext.Current.Session["PercentComplete"] = 1; } } public string RaiseCallbackEvent(string eventArguments) { int percent = this.PercentCompleted; if (percent > 100) { this.PercentCompleted = 1; return "completed"; } else { return percent.ToString() + "%"; } } protected override void OnPreRender(EventArgs e) { this.Page.ClientScript.RegisterClientScriptBlock(typeof(ProgressBar), "ProgressBar", this.GetClientSideScript(), true); base.OnPreRender(e); } protected override void Render(HtmlTextWriter writer) { System.Text.StringBuilder sb = new StringBuilder(); sb.Append(@"<table id=""ProgressBarContainer"" bgcolor=""LightSteelBlue"" border=""0"" width=""400"" style=""DISPLAY:none; POSITION: absolute; Z-INDEX: 10"">"); sb.Append(@"<tr><td colspan=""3"" style=""padding:3px 2px 2px 10px"">"); sb.Append(@"<font face=""Verdana, Arial, Helvetica, sans-serif"" size=""2"">"); sb.Append(@"<span id=""ProgressBarLabel"">Uploading...</span>"); sb.Append(@"</font></td></tr><tr><td>"); sb.Append(@"<font size=""1""> </font></td><td bgcolor=""#999999"" width=""100%"">"); sb.Append(@"<table id=""ProgressBar"" border=""0"" width=""0"" cellspacing=""0"">"); sb.Append(@"<tr><td style=""background-image:url(progressbar.gif)""> <font size=""1""> </font></td>"); sb.Append(@"</tr></table></td>"); sb.Append(@"<td><font size=""1""> </font></td></tr>"); sb.Append(@"<tr height=""5px""><td colspan=""3""></td></tr>"); sb.Append(@"</table>"); writer.Write(sb.ToString()); base.Render(writer); } private string GetClientSideScript() { System.Reflection.Assembly dll = System.Reflection.Assembly.GetExecutingAssembly(); StreamReader reader; reader = new StreamReader(dll.GetManifestResourceStream("ProgressBar.txt")); StringBuilder js = new StringBuilder(reader.ReadToEnd()); string fp = this.Page.ClientScript.GetCallbackEventReference(this, "", "UpdateProgressBar", ""); js.Replace("##InitiateCallBack##", fp); reader.Close(); return js.ToString(); } } |
列表2:ProgressBar.js
<script language="javascript"> var isCompleted=false; //这个函数初始化到服务器端的回调 function DrawProgressBar(){ ##InitiateCallBack##; if (!isCompleted) { window.setTimeout('DrawProgressBar()',200); } else { isCompleted=false; document.getElementById("ProgressBarContainer").style.display = 'none'; } } //当thecallback完成时,下列函数被调用 function UpdateProgressBar(percent){ if (percent == 'completed'){ isCompleted=true; } else{ document.getElementById("ProgressBar").width = percent; } } |