日历归档 |
|
<< < 2024 - 12 > >> | Su | Mo | Tu | We | Th | Fr | Sa | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
|
|
|
About Me |
|
|
ZhangSichu |
|
Male |
|
32 |
|
ZhangSichu@gmail.com |
|
ZhangSichu@hotmail.com |
|
ZhangSichu.com |
|
weibo.com/zhangsichu |
|
|
|
个人推荐 |
|
|
|
|
分类归档 |
|
|
|
|
My Friends |
|
|
|
|
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.
用Page_Load动态加载Trigger写的Page,Render 回来的Script. asyncPostBackControlIDs丢了。
相同的客户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); } } 问题终于比较好的解决了。
|
|
#re:UpdatePanel中动态加入AsyncPostBackTrigger出现的问题 10/16/2009 12:06:12 PM 翔
|
|
#re:UpdatePanel中动态加入AsyncPostBackTrigger出现的问题 7/23/2008 5:28:47 PM Todd
|
|
|
|
|
|