如何阻止运行Timer的UpdatePanel内Ajax ModalPopup自动关闭
问题根因
弹窗自动关闭的原因非常明确:你加的Timer1每秒触发一次异步回发,而UpdatePanel1的UpdateMode设成了Always,每次回发都会整体替换面板内的DOM内容,包括Repeater每一项里嵌的ModalPopupExtender控件。回发完成后扩展器的状态被重置为默认隐藏,刚打开的弹窗自然就直接关了。
你之前看到的「把弹窗移出UpdatePanel」的思路是对的,只是没处理好跨UpdatePanel的触发关联,下面两个方案都能直接用:
方案1:最小改动(推荐)
不用大改现有结构,调整几个点就行:
- 把Repeater的
ItemTemplate里的ModalPopupExtender、ConfirmButtonExtender全删掉,全页面只留一套弹窗控件,和DivShowData面板一起放到所有UpdatePanel外面。给MPE绑一个隐藏的按钮作为默认触发目标,不用绑定Repeater里的预览按钮:<asp:Button ID="HiddenMpeBtn" runat="server" style="display:none" /> <ajaxToolkit:modalpopupextender id="MPE_ShowData" runat="server" cancelcontrolid="ButtonDeleteCancel" okcontrolid="ButtonDeleleOkay" targetcontrolid="HiddenMpeBtn" popupcontrolid="DivShowData" backgroundcssclass="ModalPopupBG"> </ajaxToolkit:modalpopupextender> - 原来Repeater里的
BtnViewData按钮保留,后端的BtnViewData_Click事件里,根据CommandArgument传的表名把查询到的数据填充到弹窗的内容区域,最后直接调用MPE_ShowData.Show()就能打开弹窗,完全不需要在Repeater里嵌MPE,之前遇到的关联问题直接解决。 - 加两段简单的前端JS,点击预览按钮打开弹窗时临时停掉Timer,关闭弹窗时再把Timer重启,避免回发刷新关掉弹窗:
给function pauseTimer() { if (window.Timer1) Timer1._stopTimer(); } function resumeTimer() { if (window.Timer1) Timer1._startTimer(); }BtnViewData加OnClientClick="pauseTimer()",给弹窗里的确认、取消按钮加onclick="resumeTimer()"就行。 - 最后把
UpdatePanel1的UpdateMode从Always改成Conditional,保留原来Timer的AsyncPostBackTrigger配置,避免不必要的刷新。
方案2:完全无冲突方案
如果不想暂停Timer,想要查询状态刷新和弹窗预览完全互不干扰,就把页面的更新区域拆成两个独立的UpdatePanel:
- 第一个UpdatePanel只放Repeater控件,
UpdateMode设为Conditional,只加Timer的Tick作为触发器,专门负责每秒刷新查询状态。 - 第二个UpdatePanel放弹窗面板、MPE控件,
UpdateMode设为Conditional,只绑定预览按钮的事件作为触发器,只有用户点预览的时候才会刷新这块内容,Timer的回发完全碰不到这个面板,自然不会把弹窗刷关。 - Repeater绑定的时候在
ItemDataBound事件里,把每个BtnViewData通过ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(btn)注册为异步回发控件,点击后在后端事件里填充弹窗数据、调用MPE_ShowData.Show(),再更新第二个UpdatePanel即可。
踩坑提醒
别在Repeater的项模板里重复放ModalPopupExtender,全页面只需要一个弹窗实例就够,重复放不仅容易出现ID冲突、触发逻辑混乱,还会平白增加页面渲染的开销。
内容的提问来源于stack exchange,提问作者paul frith
相关产品推荐
相关产品推荐

