PAYATHON 2026

如何避免 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() 等适当方法编码,避免引号、换行或其他字符破坏脚本。

备注:内容仅供参考。