如何避免 ajaxToolkit:ModalPopupExtender 在消息关闭后自动关闭?
要让 ModalPopupExtender 在消息关闭后继续显示,可以根据是否需要执行后台代码选择处理方式:
- 只需显示提示时,在客户端调用
alert(),并阻止按钮回发。 - 需要执行后台逻辑时,在按钮事件中调用弹窗的
Show(),再通过ScriptManager.RegisterStartupScript()注册提示脚本。
为什么关闭消息后弹窗也消失了?
示例中的 Message 是一个 asp:Button,点击后会触发服务器回发。由于页面没有使用 UpdatePanel,这次回发会重新加载整个页面。
弹窗原先的打开状态保存在浏览器端。回发后,如果没有重新调用 Show(),新页面中的弹窗就不会自动打开。
Response.Write() 会直接把脚本写入响应流。浏览器执行到 alert() 时暂停,关闭提示后才继续处理页面,因此看起来像是关闭消息导致了弹窗消失。
CausesValidation="false" 只会跳过验证,不会阻止回发。
方案一:只显示提示时,阻止回发
如果消息内容已经确定,不需要访问服务器,可以将原来的 Message 按钮替换为:
<asp:Button
ID="btnMPE_Example_Panel_Like_Browser_Message"
runat="server"
Text="Message"
CausesValidation="false"
OnClientClick="alert('Message'); return false;" />
同时移除原来的服务器端 OnClick 绑定。
OnClientClick 在浏览器中执行,return false; 会取消按钮的默认提交行为。页面不会重新加载,关闭 alert() 后,原来的模态弹窗仍然保持打开。
如果不需要服务器控件,也可以使用普通按钮:
<button type="button" onclick="alert('Message');">
Message
</button>
type="button" 可以避免按钮提交表单。两种写法任选一种即可。
方案二:需要后台处理时,重新显示弹窗
如果消息需要根据保存结果、查询结果等后台逻辑生成,请保留原有按钮的服务器事件绑定,将事件处理方法替换为:
protected void btnMPE_Example_Panel_Like_Browser_Message_Click(
object sender, EventArgs e)
{
// 在这里执行需要的后台操作。
MPE_Example_Panel_Like_Browser.Show();
ScriptManager.RegisterStartupScript(
this,
GetType(),
"ModalPopupMessage",
"alert('Message');",
true);
}
Show()会在本次回发的响应中重新打开弹窗。RegisterStartupScript()负责注册提示脚本,替代直接使用Response.Write()的做法。最后一个参数为true,表示框架会添加<script>标签,脚本字符串中无需再写标签。
这种方式会先发生回发,再恢复弹窗的显示状态。如果要求提示前后都不刷新页面,应采用第一种客户端方案。
注意事项
只在需要继续显示弹窗的事件或分支中调用 Show()。如果在每次 Page_Load 中无条件调用它,点击 Close 后也可能再次打开弹窗。
原来的关闭事件可以保留:
protected void btnMPE_Example_Panel_Like_Browser_Close_Click(
object sender, EventArgs e)
{
MPE_Example_Panel_Like_Browser.Hide();
lbModal_Response_Display.Text =
"Modal Popup Example Panel Like Browser - Close";
}
如果需要让 Close 执行这个后台事件,就继续显式调用 Hide(),不要再把该按钮配置为 CancelControlID。该属性用于客户端取消操作,可能使按钮无法按预期触发服务器事件。
以后如果加入 UpdatePanel,局部回发也可能影响相关客户端控件的状态,需要根据更新范围恢复弹窗。注册异步回发脚本时,应继续使用 ScriptManager.RegisterStartupScript(),避免通过 Response.Write() 向响应中插入脚本。
示例中的消息是固定字符串。如果消息来自用户输入或动态数据,应在拼接 JavaScript 前使用 HttpUtility.JavaScriptStringEncode() 等适当方法编码,避免引号、换行或其他字符破坏脚本。
备注:内容仅供参考。
