There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5582546    Comments: 173    
 日历归档
<<  <  2024 - 12  >  >>
SuMoTuWeThFrSa
1234567
891011121314
15161718192021
22232425262728
293031
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年12月9日 星期一 RSS CLI Mine Sweeper. In Javascript.

  UpdatePanel中动态加入AsyncPostBackTrigger出现的问题
字体大小 [ ]

在一个页面中希望一个没有在Update Panel中的Button或别的可以引发PostBack的控件提交一个异步AsyncPostBack。设置UpdatePanel的 ChildrenAsTriggers为False。设置AsyncPostBackTrigger为指定的控件。
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<%= DateTime.Now.ToLongTimeString() %>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="Button1" runat="server" Text="Button" />
这段代码可以正常运行。可是这种写法不灵活,必须在设计时指定引发AsyncPostBackTrigger的控件。没有办法在运行时指定。后来在Page_Load中换成了下面的写法。想可以动态指定。
protected void Page_Load(object sender, EventArgs e)
{
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = this.Button1.ID;
this.UpdatePanel1.Triggers.Add(trigger);
}
这段代码虽然可以动态指定Trigger,可是第一次引发PostBack是一个无刷新的异步提交。可是第二次总是一个传统的提交。出现了问题。
ViewSource 看到Render回来的html几乎一模一样。都是使用Sys.WebForms.PageRequestManager._initialize (ScriptManager1, document.getElementById(form1));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([fUpdatePanel1], [Button1], [], 90);
这样的方法来注册UpdatePanel和AsyncPostBack的Control。
可是第二种写法总是出错。估计是请求一次以后回来的Script搞出的问题。
用第一种设计时指定的方法Render回来的的Script。asyncPostBackControlIDs 为Button1.
Click to Open in New Window
用Page_Load动态加载Trigger写的Page,Render 回来的Script. asyncPostBackControlIDs丢了。
Click to Open in New Window
相同的客户javascript代码注册UpdatePanel和asyncPostBackControl第二办法出了问题。估计是服务器端 UpdatePanel的代码问题。可能是Asp.Net的LifeCycle引发的原因。反射UpdatePanel的方法:发现 UpdatePanel的OnLoad会调用Initialize()
Initialize() 这个internal virtual方法中调用自己triggers的Initialize()
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!base.DesignMode && !this.ScriptManager.IsInAsyncPostBack)
{
this.Initialize();
}
}
protected internal virtual void Initialize()
{
if ((this._triggers != null) && this.ScriptManager.SupportsPartialRendering)
{
this._triggers.Initialize();
}
}
AsyncPostBack的Initialize() 会注册自己到ScriptManager.RegisterAsyncPostBackControl中
protected internal override void Initialize()
{
base.Initialize();
this._associatedControl = base.FindTargetControl(true);
this.ScriptManager.RegisterAsyncPostBackControl(this._associatedControl);

}
是为了实现客户端代码Sys.WebForms.PageRequestManager.getInstance()._updateControls([fUpdatePanel1], [Button1], [], 90); Button1这个参数。
UpdatePanel 会在OnInit()中调用this.RegisterPanel();,这个方法会注册自己到ScriptManager.RegisterUpdatePanel
private void RegisterPanel()
{
if (!base.DesignMode && !this._panelRegistered)
{
for (Control parent = this.Parent; parent != null; parent = parent.Parent)
{
UpdatePanel panel = parent as UpdatePanel;
if (panel != null)
{
panel.RegisterPanel();
break;
}
}
this.ScriptManager.RegisterUpdatePanel(this);
this._panelRegistered = true;
}
}
就是客户端代码Sys.WebForms.PageRequestManager.getInstance()._updateControls ([fUpdatePanel1], [Button1], [], 90); fUpdatePanel1这个参数。
从Render回来的代码看。UpdatePanel1每次都成功的注册到ScriptManager的UpdatePanel中没有丢。但是Button1丢了。分析注册逻辑的代码,发现On_Load的调用过程可能导致注册出错:
if (!base.DesignMode && !this.ScriptManager.IsInAsyncPostBack)
{
this.Initialize();
}
要求不是DesignMode并且不是IsInAsyncPostBack。看来是这里的要求导致在第二次Page_Load时注册Button1失败了。幸好UpdatePanel 的Initialize()也会有一次注册的机会。把代码移到Page的OnInit中:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = this.Button1.ID;
this.UpdatePanel1.Triggers.Add(trigger);
}
问题解决了。
可是在Page的OnInit时各个控件的状态还没有初始化,控件的LoadViewState() LoadPostData() 还没有被调用,各个控件的状态还不太对。不利于做逻辑处理决定是否添加这个UpdatePanel的Trigger。当Page OnInit后在Page的OnLoad时控件的状态才正确。所以还是需要在Page的Page_Load中写这段代码。需要在PageLoad时强行的为UpdatePanel1注册Button1。想尽一切办法调用一次UpdatePanel1的Initialize方法。
protected void Page_Load(object sender, EventArgs e)
{
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = this.Button1.ID;
this.UpdatePanel1.Triggers.Add(trigger);
if (this.ScriptManager1.IsInAsyncPostBack)
{
UpdatePanel1.GetType().GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(UpdatePanel1, null);
}
}
问题终于比较好的解决了。
  Posted @ 4/11/2007 9:36:18 PM | Hits (67451) | Comments (2

  Comment
 #re:UpdatePanel中动态加入AsyncPostBackTrigger出现的问题  10/16/2009 12:06:12 PM  翔
受教了
 #re:UpdatePanel中动态加入AsyncPostBackTrigger出现的问题  7/23/2008 5:28:47 PM  Todd
顶,受益匪浅
  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code