ScriptManager.RegisterClientScriptBlock 注册脚本两次



在我的自定义服务器控件的 OnPreRender 上,每次在部分回发后加载页面时,我都会注册一个警报以弹出(add_pageLoaded(function() { alert('Hi')}))。我只希望它被调用一次,但它被调用的次数与部分回发一样多。例如,在下面的代码中,如果您打开页面并单击"单击我",您将收到一个警报,再次单击,您将收到两个警报,三个 -->三个警报,依此类推。我的理解是,ScriptManager.RegisterClientScriptBlock使用scriptKey参数来检查脚本是否已注册,如果是,则不要再次注册。 我无法在 上注册此脚本!IsPostBack,因为我的自定义控件将在回发期间插入到页面中,因此使用 !IsPostBack 将不包含我的脚本。

下面是此问题的简单示例:

.ASPX:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"                                          Inherits="RegisterClientScriptExperimentation._Default" %>
<%@ Register Assembly="RegisterClientScriptExperimentation"         Namespace="RegisterClientScriptExperimentation" TagPrefix="cc" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>    
        <asp:ScriptManager ID="ScriptManager1" runat="server"/>       
        <asp:UpdatePanel runat="server">
            <ContentTemplate>
                <asp:Panel ID="panel" runat="server"/>                    
            </ContentTemplate>
        </asp:UpdatePanel>        
    </div>
    </form>
</body>
</html>

代码隐藏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
namespace RegisterClientScriptExperimentation
{
    public partial class _Default : System.Web.UI.Page
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            panel.Controls.Add(new CustomControl());
        }
    }
    public class CustomControl : CompositeControl
    {
        private Button button;
        public CustomControl()
        {
            button = new Button();
            button.Text = "Click me";
        }
        protected override void CreateChildControls()
        {
            Controls.Clear();
            Controls.Add(button);
        }
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            StringBuilder _text = new StringBuilder();
            _text.Append("var prm = Sys.WebForms.PageRequestManager.getInstance();");
            _text.Append("prm.add_pageLoaded(function() { alert('Page Loaded'); });");
            if (null != System.Web.UI.ScriptManager.GetCurrent(Page) && System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
                System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "customControlScript", _text.ToString(), true);
            else
                Page.ClientScript.RegisterStartupScript(this.GetType(), "customControlScript", _text.ToString(), true);
        }
    }
}
        if(!Page.ClientScript.IsClientScriptBlockRegistered("customControlScript") && !Page.IsPostBack)
        {
        if (null != System.Web.UI.ScriptManager.GetCurrent(Page) && System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)              
            System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "customControlScript", _text.ToString(), true);            
        else
            Page.ClientScript.RegisterStartupScript(this.GetType(), "customControlScript", _text.ToString(), true);
        }

我找到了解决这个问题的方法。

在页面事件中,在执行需要执行的任何操作后,需要从挂钩到的事件中删除函数。

例如:

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(DoSomething);
function DoSomething() {
  alert('Hello');
  Sys.WebForms.PageRequestManager.getInstance().remove_pageLoaded(DoSomething);
}

最新更新