如何在部分回发期间检查客户端脚本是不是已注册

Posted

技术标签:

【中文标题】如何在部分回发期间检查客户端脚本是不是已注册【英文标题】:How to check if client script is already registered during a partial postback如何在部分回发期间检查客户端脚本是否已注册 【发布时间】:2011-02-19 01:55:52 【问题描述】:

下面是我目前实现的代码。

if (!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey))

  ScriptManager scriptManager = ScriptManager.GetCurrent(page);
  if (scriptManager != null && scriptManager.IsInAsyncPostBack)
  
    //if a MS AJAX request, use the Scriptmanager class
    ScriptManager.RegisterStartupScript(Page, Page.GetType(), scriptKey, script, true);
  
  else
  
    //if a standard postback, use the standard ClientScript method
    Page.ClientScript.RegisterStartupScript(Page.GetType(), scriptKey, script, true);
  

我正在按照this 回答中的建议进行操作,以便我可以在两次注册启动脚本,即当有部分回发和完整回发时。

问题是Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey) 在部分回发时总是(即使之前注册了脚本)返回 false。而且我找不到 ScriptManager.IsStartupScriptRegistered (静态)方法。因此,所有部分/异步回发都会发出额外的脚本。

请注意,我在我的主页中使用的是 AjaxControlToolkit 4.1 版的脚本管理器,即ToolkitScriptManager。但我不认为这与此有关。

更新

  <asp:UpdatePanel ID="ContactDetailsUpdatePanel" UpdateMode="Conditional" runat="server">
    <Triggers>
      <asp:AsyncPostBackTrigger ControlID="UpdateContactDetailsButton" EventName="Click" />
    </Triggers>
    <ContentTemplate>
      <div id="ContactDetailsContent" class="contact_details_content">
        <div class="customer_contactdetails_left_pane">
          <div class="customer_name_field">
            <asp:Label ID="CustomerNameLabel" runat="server" Text="Customer" />
            <asp:TextBox ID="CustomerNameValue" runat="server" />
          </div>
          <div class="customer_address_field">
            <asp:Label ID="CustomerAddressLabel" runat="server" Text="Address" />
            <asp:TextBox ID="CustomerAddressValue" runat="server" />
            <asp:TextBox ID="CustomerAddressValue1" runat="server" />
            <asp:TextBox ID="CustomerAddressValue2" runat="server" />
            <asp:TextBox ID="CustomerAddressValue3" runat="server" />
          </div>
          <div class="customer_postcode_field">
            <asp:Label ID="CustomerPostcodeLabel" runat="server" Text="Postcode" />
            <asp:TextBox ID="CustomerPostcodeValue" runat="server" />
          </div>
        </div>
        <div class="customer_contactdetails_right_pane">
          <div>
            <asp:Label ID="CustomerContactLabel" runat="server" Text="Contact" />
            <asp:TextBox ID="CustomerContactValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerTelephoneLabel" runat="server" Text="Telephone" />
            <asp:TextBox ID="CustomerTelephoneValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerMobileLabel" runat="server" Text="Mobile" />
            <asp:TextBox ID="CustomerMobileValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerFaxLabel" runat="server" Text="Fax" />
            <asp:TextBox ID="CustomerFaxValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerEmailLabel" runat="server" Text="Email" />
            <asp:TextBox ID="CustomerEmailValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerWebLabel" runat="server" Text="Web" />
            <asp:TextBox ID="CustomerWebValue" runat="server" />
          </div>
        </div>
      </div>
      <div class="update_button_field">
        <asp:Button ID="UpdateContactDetailsButton" runat="server" Text="Update" 
          onclick="UpdateContactDetailsButton_Click" />
      </div>          
    </ContentTemplate>    
  </asp:UpdatePanel>

提前致谢。

注意:为了能够了解这个问题的进展,请在回复前查看this上的cmets回答。

更新 我已经通过在javascript中进行检查来实现这个问题的临时解决方案,如果脚本已经在执行,那么不要执行两次。每次部分回发时,Javascript 仍然会被多次吐出。无法阻止。

随着这篇文章的浏览量越来越多,我可以看到还有其他人可能也想回答这个问题。

【问题讨论】:

【参考方案1】:

如果你正在使用这个;

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "noPasswordMatch", script, true);

然后要检查它是否已经注册,你必须使用这个:

if (Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "noPasswordMatch"))

if (Page.ClientScript.IsClientScriptBlockRegistered("noPasswordMatch")) 不起作用!

【讨论】:

【参考方案2】:

我在 ASP.Net 中编写复合控件时遇到了同样的问题。当控件位于更新面板中时,Page.ClientScript.IsStartupScriptRegistered 不起作用。从方法 protected override void CreateChildControls() 我正在做类似的事情

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), initializeTokenInputScriptKey, initializeTokenInputScript, true);

因此,我遇到了与您在此处描述的情况类似的情况。解决我的问题的方法是将控件及其类型而不是页面和页面类型传递给 ScriptManager.RegisterStartupScript。因此代码现在看起来,

ScriptManager.RegisterStartupScript(this, this.GetType(), initializeTokenInputScriptKey, initializeTokenInputScript, true);

完成此更改后,我不再需要检查 Page.ClientScript.IsStartupScriptRegistered。现在我的控件可以使用或不使用更新面板。也没有不必要的 js 吐槽。希望这会有所帮助

【讨论】:

【参考方案3】:

我写了一个扩展方法来检查脚本是否已经注册到 ScriptManager。您可以使用相同的原理来检查启动脚本:

public static bool IsClientScriptBlockRegistered(this ScriptManager sm, string key)
        
            ReadOnlyCollection<RegisteredScript> scriptBlocks = sm.GetRegisteredClientScriptBlocks();

            foreach (RegisteredScript rs in scriptBlocks)
            
                if (rs.Key == key)
                    return true;
            

            return false;
         

【讨论】:

+1 看起来不错。但我不知道即使客户端脚本之前使用相同的密钥在 AsyncPostBacks 中注册它是否会起作用。在我接受它作为答案之前,我必须检查一下。 我试过了,它不记得以前的部分邮包了。【参考方案4】:

我通过在 javascript 中进行检查来实现此问题的临时解决方案,如果脚本已经在执行,则不要执行两次。每次部分回发时,Javascript 仍然会被多次吐出。无法阻止。

【讨论】:

这是很久以前的事了,但你有没有发现更好的? 没有。在我进一步的项目中,我从未使用过 Microsoft Ajax 控件。所以没有再遇到这种情况。【参考方案5】:

请记住,由于!,您的第一行代码是方法返回值的倒数。

if (!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey))

如果IsStartupScriptRegistered 如您所说返回false,则由于!,if 语句应评估true。这应该会导致脚本按预期注册。

您的代码基于my answer here,它基于 ASP.NET AJAX 1.0 和 ASP.NET 2.0。它可能与 .NET 3.5 有关,尽管我相信我已经在我们在 3.5 下进行的新项目中使用了上述内容,并且效果很好......

您可以发布一些标记以配合代码吗?

编辑:感谢您发布标记。

我现在注意到两件事:

您提到您正在使用ToolkitScriptManager。它是一个继承自 ScriptManager 的控件。我之前没有注意到这一点,但是您的代码仍然直接引用 ScriptManager。您说在异步回发期间脚本无法正常工作,这让我相信这是您对 ScriptManager 的引用的问题。我以前从未使用过 ToolkitScriptManager,因此我无法为您提供确切的代码,但我可以告诉您,您可能需要更新您的代码隐藏,将所有对 ScriptManager 及其方法/属性的引用更改为 ToolkitScriptManager 中的等效项.

尝试在 if 语句上添加断点并确保它的评估结果为真。如果scriptManagernull,或者scriptManager.IsInAsyncPostBackfalse,我不会感到惊讶,因为您使用的是ToolkitScriptManager

ScriptManager scriptManager = ScriptManager.GetCurrent(page);
if (scriptManager != null && scriptManager.IsInAsyncPostBack)

  //if a MS AJAX request, use the Scriptmanager class
  ScriptManager.RegisterStartupScript(Page, Page.GetType(), scriptKey, script, true);

最后 - 你的标记看起来不错,除了你不需要 &lt;Triggers&gt; 部分。触发器允许您指定更新面板之外的控件以导致部分渲染。 &lt;ContentTemplate&gt; 部分中更新面板的任何子控件都将自动执行此操作。您在“触发器”部分中定位的按钮已经在更新面板中。虽然我认为这不是您的问题的原因,但我还是会删除它。

希望这会有所帮助。

【讨论】:

我认为! 没有任何问题,因为我只想在脚本已注册时注册它。是的,我的代码基于您的回答。我的问题中已经提到了。再次感谢您的帮助。我会在星期一去办公室时发布标记。我现在没有。基本上回发是通过 AjaxControlToolkit 的 TabContainer 内的更新面板中的按钮完成的。 @Ismail 好的,我已经发布了我的答案的更新。我认为您的问题是您在使用 ToolkitScriptManager 时引用了 ScriptManager。 (见上文) @KP!我觉得你越来越糊涂了。 scriptManager.IsInAsyncPostBack 工作正常,但 Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey) 总是在部分回发中返回 false。我保持了一个断点,也看到了评估。我可以稍后适当地更改逻辑,但这里的主要问题是我需要在部分回发中找出我的脚本是否已经注册。那就是它总是告诉我它没有注册,即使它实际上已经注册了。 当我说 ScriptManager scriptManager = ToolkitScriptManager.GetCurrent(page); 时,Resharper 会给我一个警告 Access to a static member of a type via a derived type。我希望你明白这意味着什么。 @Ismail - Page.ClientScript.IsStartupScriptRegistered 应该返回 false。这是预期的行为。我只是注意到它,因为在您最初的问题中,您指出它是脚本无法正常工作的潜在问题。如果脚本未注册,则会进行注册。【参考方案6】:

你的意思是:ClientScriptManager.IsStartupScriptRegistered Method

【讨论】:

请到***.com/questions/1952817/…了解整个问题。 Page.ClientScript.IsStartupScriptRegistered() 只给我这个msdn.microsoft.com/en-us/library/62d1676x.aspx。在部分回发的情况下,它总是返回 false。 这对我没有帮助。我不知道是谁投票赞成的。我已经在使用这种方法,并且在我的问题中提到了它。

以上是关于如何在部分回发期间检查客户端脚本是不是已注册的主要内容,如果未能解决你的问题,请参考以下文章

如何检查远程 Oracle 服务器是不是已启动并正在运行

带有回发的 MVC 组件

Worklight - 如何检查客户端是不是已登录

如何在 aspx 页面回发期间使用 JQuery 维护切换打开的表行的状态?

如何检查数据库中是不是已存在该值?

如何在创建存储过程之前检查它是不是存在