我的AjaxPage对象续-一分钟让你的UserControl变成UpdatePanel
通过Callback方式扩展用户控件实现类似UpdatePanel的功能,无需更改代码,只要将用户控件继承于AjaxUserCtrl即可自动将Postback方式转换为无刷新回调方式,并可随意切换两种方式,简单快捷,一分钟就会。
简述:通过Callback方式扩展用户控件实现类似UpdatePanel的功能,无需更改代码,只要将用户控件继承于AjaxUserCtrl即可自动将Postback方式转换为无刷新回调方式,并可随意切换两种方式,简单快捷,一分钟就会。 |
本文是上一篇文章我的AjaxPage对象(Asp.NET 1.1)-借用2.0的Callback实现无刷新回调的延续,在实现Callback方法以后,这成了我目前所做的系统在提高用户体验和处理复杂页面时一个重要的补充和提升,但是就像wwonion在评论中提到的一样,单纯应用Callback方式只能在较小的场合,无法简单的处理类似DataGrid的复杂控件的Callback问题,而且原有的逻辑处理也需要移动到RaiseCallbackEvent方法中进行,如果需要在Postback和Callback方式中切换,必须放置两份代码,造成了程序复杂度增加和维护困难。
这时候,最好的方法就是能够实现类似Atlas的UpdatePanel的功能,只需要在容器类控件放置控件,按照Postback的方式撰写代码,系统自动将Postback转换为Callback方式调用,只更新该容器类控件内容,无需专门实现Callback接口和方法,经过一番思考和研究以后,对原来的AjaxPage对象进行扩展并创立了一个基于UserCtrl的AjaxUserCtrl用户控件对象,只需要将原来的用户控件继承于AjaxUserCtrl并放置在AjaxPage页面上,不需要更改任何代码,就可以让您的用户控件实现无刷新的效果了。
具体如何实现就不细讲了,大家下载代码一试就知道. 目前的代码是针对1.1的,使用2.0的朋友下载例子稍加改动就可以实现同样的功能了。
代码下载:
https://files.cnblogs.com/abei108/CallbackDemo2.rar
UpdatePanelUC是一个继承于AjaxUserCtrl的用户控件,全部按照Postback方式书写,将其继承的类改为System.Web.UI.UserControl同样可以运行。
UpdatePanelUC代码
namespace CallbackDemo
{
using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
/**//// <summary>
/// Summary description for UpdatePanelUC.
/// </summary>
public class UpdatePanelUC : AjaxUserCtrl
{
protected System.Web.UI.WebControls.DataGrid SingleGrid;
protected System.Web.UI.WebControls.DropDownList CountryList;
protected System.Web.UI.WebControls.DropDownList CityList;
protected System.Web.UI.WebControls.DataGrid DataGrid1;
private const string SQL_SELECT_CUSTOMER = "SELECT * FROM Suppliers Where Country='{0}' and CITY ='{1}'";
private const string SQL_SELECT_COUNTRY = "SELECT DISTINCT Country FROM Suppliers";
private const string SQL_SELECT_CITY = "SELECT DISTINCT CITY FROM Suppliers Where Country='{0}'";
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
CountryList.DataSource = GetNorthWindTable(SQL_SELECT_COUNTRY,ConnectString.NorthWind);
CountryList.DataTextField = "country";
CountryList.DataValueField = "country";
CountryList.DataBind();
}
}
public DataTable GetNorthWindTable(string sql,string connstr)
{
SqlDataAdapter sqladapter = new SqlDataAdapter (sql, connstr);
DataTable dt = new DataTable ();
sqladapter.Fill (dt);
sqladapter.Dispose();
return dt;
}
Web Form Designer generated code#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/**//// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.CountryList.SelectedIndexChanged += new System.EventHandler(this.CountryList_SelectedIndexChanged);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void CountryList_SelectedIndexChanged(object sender, System.EventArgs e)
{
CityList.DataSource = GetNorthWindTable(string.Format(SQL_SELECT_CITY,CountryList.SelectedItem.Value),ConnectString.NorthWind);
CityList.DataTextField = "city";
CityList.DataValueField = "city";
CityList.DataBind();
SingleGrid.DataSource = GetNorthWindTable(string.Format(SQL_SELECT_CUSTOMER,CountryList.SelectedItem.Value,CityList.SelectedItem.Value),ConnectString.NorthWind);
SingleGrid.DataBind();
}
}
}
namespace CallbackDemo
{
using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
/**//// <summary>
/// Summary description for UpdatePanelUC.
/// </summary>
public class UpdatePanelUC : AjaxUserCtrl
{
protected System.Web.UI.WebControls.DataGrid SingleGrid;
protected System.Web.UI.WebControls.DropDownList CountryList;
protected System.Web.UI.WebControls.DropDownList CityList;
protected System.Web.UI.WebControls.DataGrid DataGrid1;
private const string SQL_SELECT_CUSTOMER = "SELECT * FROM Suppliers Where Country='{0}' and CITY ='{1}'";
private const string SQL_SELECT_COUNTRY = "SELECT DISTINCT Country FROM Suppliers";
private const string SQL_SELECT_CITY = "SELECT DISTINCT CITY FROM Suppliers Where Country='{0}'";
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
CountryList.DataSource = GetNorthWindTable(SQL_SELECT_COUNTRY,ConnectString.NorthWind);
CountryList.DataTextField = "country";
CountryList.DataValueField = "country";
CountryList.DataBind();
}
}
public DataTable GetNorthWindTable(string sql,string connstr)
{
SqlDataAdapter sqladapter = new SqlDataAdapter (sql, connstr);
DataTable dt = new DataTable ();
sqladapter.Fill (dt);
sqladapter.Dispose();
return dt;
}
Web Form Designer generated code#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/**//// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.CountryList.SelectedIndexChanged += new System.EventHandler(this.CountryList_SelectedIndexChanged);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void CountryList_SelectedIndexChanged(object sender, System.EventArgs e)
{
CityList.DataSource = GetNorthWindTable(string.Format(SQL_SELECT_CITY,CountryList.SelectedItem.Value),ConnectString.NorthWind);
CityList.DataTextField = "city";
CityList.DataValueField = "city";
CityList.DataBind();
SingleGrid.DataSource = GetNorthWindTable(string.Format(SQL_SELECT_CUSTOMER,CountryList.SelectedItem.Value,CityList.SelectedItem.Value),ConnectString.NorthWind);
SingleGrid.DataBind();
}
}
}
在AjaxDemo.aspx中演示了Postback、Callback以及UpdatePanel模式的效果,可以看到我们只是简单将上面写好的UpdatePanelUC拖拽在该页面中,并且放置同样的用户控件不会互相影响
在SingleForm.aspx则是新建一个WebForm,使其从AjaxPage继承,然后将UpdatePanelUC拖拽到页面上,执行,你会看到该控件以Callback方式执行,非常轻松。
本来在第一篇文章写完不久就有这个想法,但是工作太忙就搁下来了,最近才有时间继续进行研究,刚写好就发出来,希望能够抛砖印玉,多与大家交流,不对之处还请大家斧正。
附AjaxPage和AjaxUserCtrl代码
AjaxPage代码
using System;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
namespace CallbackDemo
{
/**//// <summary>
/// 从System.Web.UI.Page继承,扩展了对Callback的支持
/// </summary>
public class AjaxPage:System.Web.UI.Page
{
private bool m_iscallback;
private string m_callbackid;
private NameValueCollection m_requestValueCollection;
private ICallbackEventHandler m_callbackControl;
private string m_formid;
/**//// <summary>
/// 判断本次提交是Callback还是Postback
/// </summary>
public bool IsCallback
{
get {return m_iscallback;}
}
/**//// <summary>
/// 回传的控件ID,此控件的RaiseCallbackEvent和GetCallbackResult方法将被触发
/// </summary>
public string CallbackID
{
get {return m_callbackid;}
}
public string FormID
{
get
{
if (m_formid==null)
m_formid = GetFormID();
return m_formid;
}
set {m_formid = value;}
}
public AjaxPage()
{
//如果将页面作为CallbackControl.则需要设置一个默认ID
this.ID = "AjaxPage";
m_iscallback = false;
m_callbackid = string.Empty;
m_requestValueCollection = null;
m_formid = null;
}
protected override void OnInit(EventArgs e)
{
//注册必要的脚本和方法
this.RegisterStartupScript("callbackscript","<SCRIPT LANGUAGE=\"javascript\" SRC=\""+this.Request.ApplicationPath+"/asp2_Callback.js\"></SCRIPT>");
this.RegisterStartupScript("mycallback",BuildCallbackCommand());
//根据Post的方式返回Request.QueryString或者Request.Form集合
m_requestValueCollection = this.DeterminePostBackMode();
if (this.m_requestValueCollection != null)
{
//检查回传值确定是否是Callback方式回传
m_callbackid = this.m_requestValueCollection["__CALLBACKID"];
if (m_callbackid != null)
{
m_iscallback = true;
}
}
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (IsCallback)
PrepareCallback(CallbackID);
}
protected override void Render(HtmlTextWriter writer)
{
if (this.IsCallback)
{
this.RenderCallback();
}
else
base.Render(writer);
}
/**//// <summary>
/// 根据callbackControlID查找控件,如果该控件实现了ICallbackEventHandler接口就触发RaiseCallbackEvent方法
/// </summary>
/// <param name="callbackControlID">Callback控件ID</param>
private void PrepareCallback(string callbackControlID)
{
this.Response.Cache.SetNoStore();
try
{
string callbackparam = this.m_requestValueCollection["__CALLBACKPARAM"];
if (this.ID == callbackControlID)
this.m_callbackControl = (ICallbackEventHandler)this;
else
this.m_callbackControl = this.FindControl(callbackControlID) as ICallbackEventHandler;
if (this.m_callbackControl != null)
{
this.m_callbackControl.RaiseCallbackEvent(callbackparam);
return;
}
else
{
//触发AjaxUserCtrl事件
for (int i=0;i<this.AllAjaxUserCtrls.Count;i++)
{
AjaxUserCtrl auc = (AllAjaxUserCtrls[i] as AjaxUserCtrl);
if (auc!=null && auc.ID==callbackControlID)
{
this.m_callbackControl = auc;
auc.RaiseCallbackEvent(callbackparam);
return;
}
}
throw new InvalidOperationException(string.Format("Page_CallBackTargetInvalid, Callback Control ID:{0}", new object[] { callbackControlID }));
}
}
catch (Exception exception)
{
this.Response.Clear();
this.Response.Write('e');
if (this.Context.IsCustomErrorEnabled)
{
this.Response.Write(string.Format("Page_CallBackError"));
return;
}
this.Response.Write(HttpUtility.HtmlEncode(exception.Message));
return;
}
}
/**//// <summary>
/// 如果是Callback方式则在Render中执行该方法,将m_callbackControl.GetCallbackResult()返回到客户端
/// </summary>
private void RenderCallback()
{
string cbsc = this.m_requestValueCollection["__CALLBACKLOADSCRIPT"];
bool flag = !(cbsc==null || cbsc==string.Empty);
try
{
string callbackidx = null;
if (flag)
{
callbackidx = this.m_requestValueCollection["__CALLBACKINDEX"];
if ((callbackidx==null) || (callbackidx==string.Empty))
{
throw new HttpException(string.Format("Page_CallBackInvalid"));
}
for (int idx = 0; idx < callbackidx.Length; idx++)
{
if (!char.IsDigit(callbackidx, idx))
{
throw new HttpException(string.Format("Page_CallBackInvalid"));
}
}
this.Response.Write("<script>parent.__pendingCallbacks[");
this.Response.Write(callbackidx);
this.Response.Write("].xmlRequest.responseText=\"");
}
if (this.m_callbackControl != null)
{
string callbackrlt = this.m_callbackControl.GetCallbackResult();
this.Response.Write('s');
this.Response.Write(callbackrlt);
}
if (flag)
{
this.Response.Write("\";parent.__pendingCallbacks[");
this.Response.Write(callbackidx);
this.Response.Write("].xmlRequest.readyState=4;parent.WebForm_CallbackComplete();</script>");
}
}
catch (Exception exception1)
{
this.Response.Clear();
this.Response.Write('e');
if (this.Context.IsCustomErrorEnabled)
{
this.Response.Write(string.Format("Page_CallBackError"));
return;
}
this.Response.Write(HttpUtility.HtmlEncode(exception1.Message));
}
}
生成Callback方法#region 生成Callback方法
public string GetCallbackEventReference(Control control, string argument, string clientCallback, string context)
{
return GetCallbackEventReference(control,argument,clientCallback,context,null,false);
}
public string GetCallbackEventReference(Control control, string argument, string clientCallback, string context, string clientErrorCallback)
{
return GetCallbackEventReference(control,argument,clientCallback,context,clientErrorCallback,false);
}
public string GetCallbackEventReference(Control control, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
if (!(control is ICallbackEventHandler))
{
throw new InvalidOperationException(string.Format("Page_CallBackTargetInvalid, ID:{0}", new object[] { control.UniqueID }));
}
return GetCallbackEventReference("'" + control.UniqueID + "'",argument,clientCallback,context,clientErrorCallback,false);
}
public string GetCallbackEventReference(string target, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
{
if (argument == null)
{
argument = "null";
}
else if (argument.Length == 0)
{
argument = "\"\"";
}
if (context == null)
{
context = "null";
}
else if (context.Length == 0)
{
context = "\"\"";
}
return ("WebForm_MyCallback(" + target + "," + argument + "," + clientCallback + "," + context + "," + ((clientErrorCallback == null) ? "null" : clientErrorCallback) + "," + (useAsync ? "true" : "false") + ")");
}
#endregion
/**//// <summary>
/// WebForm_MyCallback是对系统提供的WebForm_DoCallback方法进行封装,以加入theForm参数
/// </summary>
/// <returns></returns>
private string BuildCallbackCommand()
{
StringBuilder sb = new StringBuilder();
sb.Append("<script type=\"text/javascript\" language=\"javascript\">\r\n");
sb.Append("var theForm = document.forms['"+FormID+"'];\r\n");
sb.Append("if (!theForm) {theForm = document."+FormID+";}\r\n");
//如果有AjaxUserCtrl则需要加入AjaxUserCtrl的支持
if (this.AllAjaxUserCtrls.Count>0)
{
sb.Append("var ajaxuserctrlArray = \""+GetAjaxUserCtrlArray()+"\".split('|');\r\n");
sb.Append("Function.createDelegate = function(instance,method){return function(){method.apply(instance,arguments);}};\r\n");
sb.Append("aspnetDoPostBack = window.__doPostBack;\r\n");
sb.Append("if (aspnetDoPostBack) {window.__doPostBack = Function.createDelegate(this, this.doCallbackPostBack);}\r\n");
sb.Append("function doCallbackPostBack(eventTarget, eventArgument) {\r\n");
sb.Append(" theForm.__EVENTTARGET.value = eventTarget.split(\"$\").join(\":\");\r\n");
sb.Append(" theForm.__EVENTARGUMENT.value = eventArgument;\r\n");
sb.Append(" var uid = CheckInAjaxUserCtrl(ajaxuserctrlArray,eventTarget);\r\n");
sb.Append(" if (uid)\r\n");
sb.Append(" {\r\n");
sb.Append(" var ajaxuserctrl = eventTarget.replace(\"$\",\":\").split(\":\")[0];\r\n");
sb.Append(" WebForm_MyCallback(ajaxuserctrl, ajaxuserctrl, UpdateAjaxUserCtrl, document.getElementById(ajaxuserctrl), null, false);\r\n");
sb.Append(" }\r\n");
sb.Append(" else\r\n");
sb.Append(" {\r\n");
sb.Append(" theForm.submit();\r\n");
sb.Append(" }\r\n");
sb.Append(" \r\n");
sb.Append(" }\r\n");
//ajaxuserctrl查找函数
sb.Append("function CheckInAjaxUserCtrl(array, eventTarget) {\r\n");
sb.Append(" var i;\r\n");
sb.Append(" var CheckInAjaxUserCtrl = null;\r\n");
sb.Append(" for (i = 0; i < array.length; i++) {\r\n");
sb.Append(" if (eventTarget.indexOf(array[i])!=-1)\r\n");
//此行用于取回触发事件控件名
sb.Append(" { CheckInAjaxUserCtrl = eventTarget.substring(array[i].length+1,eventTarget.length);}\r\n");
sb.Append(" }\r\n");
sb.Append(" return CheckInAjaxUserCtrl;\r\n");
sb.Append(" }\r\n");
}
sb.Append("function WebForm_MyCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)\r\n");
sb.Append("{\r\n");
sb.Append(" __theFormPostData = \"\";\r\n");
sb.Append(" WebForm_InitCallback();\r\n");
sb.Append(" WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)\r\n");
sb.Append("}\r\n");
sb.Append("</Script>\r\n");
sb.Append("\r\n");
return sb.ToString();
}
/**//// <summary>
/// 重写VerifyRenderingInServerForm方法,当Callback方式回传时就不再进行Verify
/// </summary>
/// <param name="control"></param>
public override void VerifyRenderingInServerForm(Control control)
{
if (!this.IsCallback)
base.VerifyRenderingInServerForm(control);
}
/**//// <summary>
/// 因为Form无法直接读取,只能采用遍历控件查找
/// </summary>
/// <returns></returns>
public virtual string GetFormID()
{
for (int i=0;i<this.Controls.Count;i++)
{
if (this.Controls[i] is System.Web.UI.HtmlControls.HtmlForm)
return (this.Controls[i] as System.Web.UI.HtmlControls.HtmlForm).ID;
}
return "Form1";
}
for AjaxUserCtrl#region for AjaxUserCtrl
private ArrayList m_ajaxuserctrls;
public ArrayList AllAjaxUserCtrls
{
get
{
if (m_ajaxuserctrls==null)
{
m_ajaxuserctrls = new ArrayList();
}
return m_ajaxuserctrls;
}
}
public virtual void RegisterAjaxUserCtrl(AjaxUserCtrl ajaxuserctrl)
{
if (ajaxuserctrl==null)
{
throw new ArgumentException("ajaxuserctrl");
}
if ((this.AllAjaxUserCtrls != null) && !this.AllAjaxUserCtrls.Contains(ajaxuserctrl))
{
AllAjaxUserCtrls.Add(ajaxuserctrl);
}
}
private string GetAjaxUserCtrlArray()
{
string array = string.Empty;
for (int i=0;i<this.AllAjaxUserCtrls.Count;i++)
{
array += (AllAjaxUserCtrls[i] as AjaxUserCtrl).UniqueID+"|";
}
return array.Remove(array.Length-1,1);
}
#endregion
}
}
using System;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
namespace CallbackDemo
{
/**//// <summary>
/// 从System.Web.UI.Page继承,扩展了对Callback的支持
/// </summary>
public class AjaxPage:System.Web.UI.Page
{
private bool m_iscallback;
private string m_callbackid;
private NameValueCollection m_requestValueCollection;
private ICallbackEventHandler m_callbackControl;
private string m_formid;
/**//// <summary>
/// 判断本次提交是Callback还是Postback
/// </summary>
public bool IsCallback
{
get {return m_iscallback;}
}
/**//// <summary>
/// 回传的控件ID,此控件的RaiseCallbackEvent和GetCallbackResult方法将被触发
/// </summary>
public string CallbackID
{
get {return m_callbackid;}
}
public string FormID
{
get
{
if (m_formid==null)
m_formid = GetFormID();
return m_formid;
}
set {m_formid = value;}
}
public AjaxPage()
{
//如果将页面作为CallbackControl.则需要设置一个默认ID
this.ID = "AjaxPage";
m_iscallback = false;
m_callbackid = string.Empty;
m_requestValueCollection = null;
m_formid = null;
}
protected override void OnInit(EventArgs e)
{
//注册必要的脚本和方法
this.RegisterStartupScript("callbackscript","<SCRIPT LANGUAGE=\"javascript\" SRC=\""+this.Request.ApplicationPath+"/asp2_Callback.js\"></SCRIPT>");
this.RegisterStartupScript("mycallback",BuildCallbackCommand());
//根据Post的方式返回Request.QueryString或者Request.Form集合
m_requestValueCollection = this.DeterminePostBackMode();
if (this.m_requestValueCollection != null)
{
//检查回传值确定是否是Callback方式回传
m_callbackid = this.m_requestValueCollection["__CALLBACKID"];
if (m_callbackid != null)
{
m_iscallback = true;
}
}
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (IsCallback)
PrepareCallback(CallbackID);
}
protected override void Render(HtmlTextWriter writer)
{
if (this.IsCallback)
{
this.RenderCallback();
}
else
base.Render(writer);
}
/**//// <summary>
/// 根据callbackControlID查找控件,如果该控件实现了ICallbackEventHandler接口就触发RaiseCallbackEvent方法
/// </summary>
/// <param name="callbackControlID">Callback控件ID</param>
private void PrepareCallback(string callbackControlID)
{
this.Response.Cache.SetNoStore();
try
{
string callbackparam = this.m_requestValueCollection["__CALLBACKPARAM"];
if (this.ID == callbackControlID)
this.m_callbackControl = (ICallbackEventHandler)this;
else
this.m_callbackControl = this.FindControl(callbackControlID) as ICallbackEventHandler;
if (this.m_callbackControl != null)
{
this.m_callbackControl.RaiseCallbackEvent(callbackparam);
return;
}
else
{
//触发AjaxUserCtrl事件
for (int i=0;i<this.AllAjaxUserCtrls.Count;i++)
{
AjaxUserCtrl auc = (AllAjaxUserCtrls[i] as AjaxUserCtrl);
if (auc!=null && auc.ID==callbackControlID)
{
this.m_callbackControl = auc;
auc.RaiseCallbackEvent(callbackparam);
return;
}
}
throw new InvalidOperationException(string.Format("Page_CallBackTargetInvalid, Callback Control ID:{0}", new object[] { callbackControlID }));
}
}
catch (Exception exception)
{
this.Response.Clear();
this.Response.Write('e');
if (this.Context.IsCustomErrorEnabled)
{
this.Response.Write(string.Format("Page_CallBackError"));
return;
}
this.Response.Write(HttpUtility.HtmlEncode(exception.Message));
return;
}
}
/**//// <summary>
/// 如果是Callback方式则在Render中执行该方法,将m_callbackControl.GetCallbackResult()返回到客户端
/// </summary>
private void RenderCallback()
{
string cbsc = this.m_requestValueCollection["__CALLBACKLOADSCRIPT"];
bool flag = !(cbsc==null || cbsc==string.Empty);
try
{
string callbackidx = null;
if (flag)
{
callbackidx = this.m_requestValueCollection["__CALLBACKINDEX"];
if ((callbackidx==null) || (callbackidx==string.Empty))
{
throw new HttpException(string.Format("Page_CallBackInvalid"));
}
for (int idx = 0; idx < callbackidx.Length; idx++)
{
if (!char.IsDigit(callbackidx, idx))
{
throw new HttpException(string.Format("Page_CallBackInvalid"));
}
}
this.Response.Write("<script>parent.__pendingCallbacks[");
this.Response.Write(callbackidx);
this.Response.Write("].xmlRequest.responseText=\"");
}
if (this.m_callbackControl != null)
{
string callbackrlt = this.m_callbackControl.GetCallbackResult();
this.Response.Write('s');
this.Response.Write(callbackrlt);
}
if (flag)
{
this.Response.Write("\";parent.__pendingCallbacks[");
this.Response.Write(callbackidx);
this.Response.Write("].xmlRequest.readyState=4;parent.WebForm_CallbackComplete();</script>");
}
}
catch (Exception exception1)
{
this.Response.Clear();
this.Response.Write('e');
if (this.Context.IsCustomErrorEnabled)
{
this.Response.Write(string.Format("Page_CallBackError"));
return;
}
this.Response.Write(HttpUtility.HtmlEncode(exception1.Message));
}
}
生成Callback方法#region 生成Callback方法
public string GetCallbackEventReference(Control control, string argument, string clientCallback, string context)
{
return GetCallbackEventReference(control,argument,clientCallback,context,null,false);
}
public string GetCallbackEventReference(Control control, string argument, string clientCallback, string context, string clientErrorCallback)
{
return GetCallbackEventReference(control,argument,clientCallback,context,clientErrorCallback,false);
}
public string GetCallbackEventReference(Control control, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
if (!(control is ICallbackEventHandler))
{
throw new InvalidOperationException(string.Format("Page_CallBackTargetInvalid, ID:{0}", new object[] { control.UniqueID }));
}
return GetCallbackEventReference("'" + control.UniqueID + "'",argument,clientCallback,context,clientErrorCallback,false);
}
public string GetCallbackEventReference(string target, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
{
if (argument == null)
{
argument = "null";
}
else if (argument.Length == 0)
{
argument = "\"\"";
}
if (context == null)
{
context = "null";
}
else if (context.Length == 0)
{
context = "\"\"";
}
return ("WebForm_MyCallback(" + target + "," + argument + "," + clientCallback + "," + context + "," + ((clientErrorCallback == null) ? "null" : clientErrorCallback) + "," + (useAsync ? "true" : "false") + ")");
}
#endregion
/**//// <summary>
/// WebForm_MyCallback是对系统提供的WebForm_DoCallback方法进行封装,以加入theForm参数
/// </summary>
/// <returns></returns>
private string BuildCallbackCommand()
{
StringBuilder sb = new StringBuilder();
sb.Append("<script type=\"text/javascript\" language=\"javascript\">\r\n");
sb.Append("var theForm = document.forms['"+FormID+"'];\r\n");
sb.Append("if (!theForm) {theForm = document."+FormID+";}\r\n");
//如果有AjaxUserCtrl则需要加入AjaxUserCtrl的支持
if (this.AllAjaxUserCtrls.Count>0)
{
sb.Append("var ajaxuserctrlArray = \""+GetAjaxUserCtrlArray()+"\".split('|');\r\n");
sb.Append("Function.createDelegate = function(instance,method){return function(){method.apply(instance,arguments);}};\r\n");
sb.Append("aspnetDoPostBack = window.__doPostBack;\r\n");
sb.Append("if (aspnetDoPostBack) {window.__doPostBack = Function.createDelegate(this, this.doCallbackPostBack);}\r\n");
sb.Append("function doCallbackPostBack(eventTarget, eventArgument) {\r\n");
sb.Append(" theForm.__EVENTTARGET.value = eventTarget.split(\"$\").join(\":\");\r\n");
sb.Append(" theForm.__EVENTARGUMENT.value = eventArgument;\r\n");
sb.Append(" var uid = CheckInAjaxUserCtrl(ajaxuserctrlArray,eventTarget);\r\n");
sb.Append(" if (uid)\r\n");
sb.Append(" {\r\n");
sb.Append(" var ajaxuserctrl = eventTarget.replace(\"$\",\":\").split(\":\")[0];\r\n");
sb.Append(" WebForm_MyCallback(ajaxuserctrl, ajaxuserctrl, UpdateAjaxUserCtrl, document.getElementById(ajaxuserctrl), null, false);\r\n");
sb.Append(" }\r\n");
sb.Append(" else\r\n");
sb.Append(" {\r\n");
sb.Append(" theForm.submit();\r\n");
sb.Append(" }\r\n");
sb.Append(" \r\n");
sb.Append(" }\r\n");
//ajaxuserctrl查找函数
sb.Append("function CheckInAjaxUserCtrl(array, eventTarget) {\r\n");
sb.Append(" var i;\r\n");
sb.Append(" var CheckInAjaxUserCtrl = null;\r\n");
sb.Append(" for (i = 0; i < array.length; i++) {\r\n");
sb.Append(" if (eventTarget.indexOf(array[i])!=-1)\r\n");
//此行用于取回触发事件控件名
sb.Append(" { CheckInAjaxUserCtrl = eventTarget.substring(array[i].length+1,eventTarget.length);}\r\n");
sb.Append(" }\r\n");
sb.Append(" return CheckInAjaxUserCtrl;\r\n");
sb.Append(" }\r\n");
}
sb.Append("function WebForm_MyCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)\r\n");
sb.Append("{\r\n");
sb.Append(" __theFormPostData = \"\";\r\n");
sb.Append(" WebForm_InitCallback();\r\n");
sb.Append(" WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)\r\n");
sb.Append("}\r\n");
sb.Append("</Script>\r\n");
sb.Append("\r\n");
return sb.ToString();
}
/**//// <summary>
/// 重写VerifyRenderingInServerForm方法,当Callback方式回传时就不再进行Verify
/// </summary>
/// <param name="control"></param>
public override void VerifyRenderingInServerForm(Control control)
{
if (!this.IsCallback)
base.VerifyRenderingInServerForm(control);
}
/**//// <summary>
/// 因为Form无法直接读取,只能采用遍历控件查找
/// </summary>
/// <returns></returns>
public virtual string GetFormID()
{
for (int i=0;i<this.Controls.Count;i++)
{
if (this.Controls[i] is System.Web.UI.HtmlControls.HtmlForm)
return (this.Controls[i] as System.Web.UI.HtmlControls.HtmlForm).ID;
}
return "Form1";
}
for AjaxUserCtrl#region for AjaxUserCtrl
private ArrayList m_ajaxuserctrls;
public ArrayList AllAjaxUserCtrls
{
get
{
if (m_ajaxuserctrls==null)
{
m_ajaxuserctrls = new ArrayList();
}
return m_ajaxuserctrls;
}
}
public virtual void RegisterAjaxUserCtrl(AjaxUserCtrl ajaxuserctrl)
{
if (ajaxuserctrl==null)
{
throw new ArgumentException("ajaxuserctrl");
}
if ((this.AllAjaxUserCtrls != null) && !this.AllAjaxUserCtrls.Contains(ajaxuserctrl))
{
AllAjaxUserCtrls.Add(ajaxuserctrl);
}
}
private string GetAjaxUserCtrlArray()
{
string array = string.Empty;
for (int i=0;i<this.AllAjaxUserCtrls.Count;i++)
{
array += (AllAjaxUserCtrls[i] as AjaxUserCtrl).UniqueID+"|";
}
return array.Remove(array.Length-1,1);
}
#endregion
}
}
AjaxUserCtrl代码
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
using System.IO;
using System.Globalization;
using System.Text;
namespace CallbackDemo
{
/**//// <summary>
/// Summary description for AjaxUserCtrl.
/// </summary>
public class AjaxUserCtrl:System.Web.UI.UserControl,ICallbackEventHandler
{
private string rlt = string.Empty;
private bool PartialRender = false;
private bool m_iscallback;
public bool IsCallback
{
get {return m_iscallback;}
set {m_iscallback = value;}
}
public AjaxUserCtrl()
{
m_iscallback = true;
}
protected override void OnInit(EventArgs e)
{
if ((this.Page == null) || !(this.Page is AjaxPage))
{
throw new Exception("The Page can't be null and Type of Page must be AjaxPage");
}
if ((this.ID==null) || (this.ID==string.Empty))
{
throw new InvalidOperationException("AjaxUserCtrl must have an explicit ID.");
}
if (IsCallback)
{
(Page as AjaxPage).RegisterAjaxUserCtrl(this);
Page.RegisterClientScriptBlock("ajaxuserctrl",BuildScript());
}
base.OnInit(e);
}
protected override void Render(HtmlTextWriter writer)
{
this.Page.VerifyRenderingInServerForm(this);
base.Render(writer);
}
public string GetCallbackResult()
{
if (PartialRender)
{
StringWriter writer1 = new StringWriter(CultureInfo.InvariantCulture);
HtmlTextWriter writer2 = new HtmlTextWriter(writer1);
this.RenderControl(writer2);
writer2.Flush();
writer2.Close();
rlt = writer1.ToString();
}
return rlt;
}
public void RaiseCallbackEvent(string eventArgument)
{
if (eventArgument == null || eventArgument == String.Empty)
{
rlt = "Empty";
return;
}
if (eventArgument == this.UniqueID)
{
PartialRender = true;
return;
}
}
/**//// <summary>
/// 输出AjaxUserCtrl回调函数
/// </summary>
/// <returns>包含回调函数的字符串</returns>
private string BuildScript()
{
StringBuilder sb = new StringBuilder();
sb.Append("<script type=\"text/javascript\" language=\"javascript\">\r\n");
sb.Append(" function UpdateAjaxUserCtrl(responseText, context) {\r\n");
sb.Append(" if (context != null)\r\n");
sb.Append(" context.innerHTML = responseText;\r\n");
sb.Append(" }\r\n");
sb.Append("</Script>\r\n");
return sb.ToString();
}
/**//// <summary>
/// 在UserCtrl进行Render时输出一个Div区域用于回调函数填充回传的值
/// </summary>
/// <param name="writer"></param>
protected override void RenderChildren(HtmlTextWriter writer)
{
if (!IsPostBack)
{
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
writer.RenderBeginTag(HtmlTextWriterTag.Div);
base.RenderChildren(writer);
writer.RenderEndTag();
}
else
base.RenderChildren(writer);
}
}
}
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
using System.IO;
using System.Globalization;
using System.Text;
namespace CallbackDemo
{
/**//// <summary>
/// Summary description for AjaxUserCtrl.
/// </summary>
public class AjaxUserCtrl:System.Web.UI.UserControl,ICallbackEventHandler
{
private string rlt = string.Empty;
private bool PartialRender = false;
private bool m_iscallback;
public bool IsCallback
{
get {return m_iscallback;}
set {m_iscallback = value;}
}
public AjaxUserCtrl()
{
m_iscallback = true;
}
protected override void OnInit(EventArgs e)
{
if ((this.Page == null) || !(this.Page is AjaxPage))
{
throw new Exception("The Page can't be null and Type of Page must be AjaxPage");
}
if ((this.ID==null) || (this.ID==string.Empty))
{
throw new InvalidOperationException("AjaxUserCtrl must have an explicit ID.");
}
if (IsCallback)
{
(Page as AjaxPage).RegisterAjaxUserCtrl(this);
Page.RegisterClientScriptBlock("ajaxuserctrl",BuildScript());
}
base.OnInit(e);
}
protected override void Render(HtmlTextWriter writer)
{
this.Page.VerifyRenderingInServerForm(this);
base.Render(writer);
}
public string GetCallbackResult()
{
if (PartialRender)
{
StringWriter writer1 = new StringWriter(CultureInfo.InvariantCulture);
HtmlTextWriter writer2 = new HtmlTextWriter(writer1);
this.RenderControl(writer2);
writer2.Flush();
writer2.Close();
rlt = writer1.ToString();
}
return rlt;
}
public void RaiseCallbackEvent(string eventArgument)
{
if (eventArgument == null || eventArgument == String.Empty)
{
rlt = "Empty";
return;
}
if (eventArgument == this.UniqueID)
{
PartialRender = true;
return;
}
}
/**//// <summary>
/// 输出AjaxUserCtrl回调函数
/// </summary>
/// <returns>包含回调函数的字符串</returns>
private string BuildScript()
{
StringBuilder sb = new StringBuilder();
sb.Append("<script type=\"text/javascript\" language=\"javascript\">\r\n");
sb.Append(" function UpdateAjaxUserCtrl(responseText, context) {\r\n");
sb.Append(" if (context != null)\r\n");
sb.Append(" context.innerHTML = responseText;\r\n");
sb.Append(" }\r\n");
sb.Append("</Script>\r\n");
return sb.ToString();
}
/**//// <summary>
/// 在UserCtrl进行Render时输出一个Div区域用于回调函数填充回传的值
/// </summary>
/// <param name="writer"></param>
protected override void RenderChildren(HtmlTextWriter writer)
{
if (!IsPostBack)
{
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
writer.RenderBeginTag(HtmlTextWriterTag.Div);
base.RenderChildren(writer);
writer.RenderEndTag();
}
else
base.RenderChildren(writer);
}
}
}
posted on 2006-09-12 10:32 Gao.Steven 阅读(2691) 评论(9) 编辑 收藏 举报