ASP.Net - AJAX UpdatePanel 中的 Javascript

10

我遇到了一个问题,在UpdatePanel中运行外部JavaScript文件中的JavaScript时出现了问题。我正在尝试在ListView中使用颜色选择器,而ListView在UpdatePanel中。

我正在使用这个颜色选择器

以下是我已经缩小的问题范围:

  • 如果我在不在UpdatePanel之内的文本框上使用颜色选择器,则在所有回发期间都可以正常工作。

  • 如果我在UpdatePanel中的文本框上使用颜色选择器,则在执行异步回发(单击ListView中的“EDIT”按钮)后它能正常工作。一旦UpdatePanel完成回发,再次单击文本框将无法显示颜色选择器。当文本框位于ListView的InsertItemTemplateEditItemTemplate中时也是如此。

如果您想要复制它,只需下载颜色选择器(它是免费的),然后将其添加到一个网页中...

<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>

<div>
    <asp:UpdatePanel ID="panel1" runat="server">
        <ContentTemplate>
            <asp:TextBox runat="server" ID="textbox" CssClass="color" />
            <asp:Button ID="Button1" runat="server" Text="Button" />
        </ContentTemplate>
    </asp:UpdatePanel>
</div>

当页面加载时,颜色选择器功能正常。当您单击按钮(执行回发)时,颜色选择器将不再工作。

有什么想法吗?

4个回答

16

经过异步回传后,任何启动脚本都不会运行,这很可能是为什么 AJAX 回调后无法正常工作的原因。颜色选择器可能有一些需要在页面加载时执行的函数。

我已经遇到了这种情况很多次,所以我编写了一个小方法在后端注册我的脚本,它可以处理异步和非异步回传。以下是基本的概述:

private void RegisterClientStartupScript(string scriptKey, string scriptText)
{
    ScriptManager sManager = ScriptManager.GetCurrent(this.Page);

    if (sManager != null && sManager.IsInAsyncPostBack)
    {
        //if a MS AJAX request, use the Scriptmanager class
        ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), scriptKey, scriptText, true);
    }
    else
    {
        //if a standard postback, use the standard ClientScript method
        scriptText = string.Concat("Sys.Application.add_load(function(){", scriptText, "});");
        this.Page.ClientScript.RegisterStartupScript(this.Page.GetType(), scriptKey, scriptText, true);
    }
}

我实际上将上述代码封装成一个基本页面类,以便我正在使用的任何页面都可以调用this.RegisterClientStartupScript(...)。要这样做,只需创建一个基本页类并在其中包含它(确保标记为protected而不是private,否则继承页面类将无法访问它)。

使用上述代码,无论页面是在进行postback还是callback,我都可以自信地注册客户端脚本。如果您正在使用外部脚本文件,您可能可以修改上述方法以注册外部脚本而不是内联脚本。有关更多详细信息,请参阅ScriptManager类,因为有几种脚本注册方法...


谢谢。我使用了这种方法,并将jscolor.init()方法作为scriptText调用,现在它可以工作了。 - Ryan Alford
我更喜欢使用扩展方法来代替创建基础页面类,谢谢。+1 - IsmailS
请问您能帮我理解为什么在标准的 postback 中要将它放在 "Sys.Application.add_load(function(){}" 中吗?我可以在没有放置 ScriptManager 控件的页面上使用它吗? - IsmailS
@KP. 我认为您可以帮助我解决这个问题。https://dev59.com/uHE85IYBdhLWcg3wVh84 - IsmailS
1
@Ismail:说实话,我不记得为什么需要 add_load 函数(自从我编写上述方法以来已经很长时间了),但我记得它与在 postback 期间注册脚本时,在某些情况下可能无法触发或提前触发有关。我在网上找到了 add_load 的解决方案,它立即解决了问题,所以我一直使用它。 - KP.

2

在查看jscolor源代码后,我注意到它在窗口加载时初始化所有内容。因此,在UpdatePanel中,您可能需要重新初始化,如下所示:

function yourInit(){
   /* keep in mind that the jscolor.js file has no way to determine
      that the script has already been initialized, and you may end
      up initializing it twice, unless you remove jscolor.install();
   */

   if (typeof(jscolor) !== 'undefined'){
      jscolor.init();
   }
}
if (typeof(Sys) !== 'undefined'){
   Sys.UI.DomEvent.addHandler(window, "load", yourInit);
}
else{
   // no ASP.NET AJAX, use your favorite event
   // attachment method here
}

如果您决定将jscolor脚本放在UpdatePanel中,则还需要在jscolor.js的末尾添加以下内容:
if(Sys && Sys.Application){
   Sys.Application.notifyScriptLoaded();
}

如果 (window.Sys... - thorn0

1
你尝试过使用ScriptManager.RegisterStartupScript吗?它允许你在异步回发时从服务器向页面添加JavaScript。

0
我猜测,jscolor.js 代码只在页面首次加载时运行以设置颜色选择器,因此当服务器重新生成控件时,您会失去 jscolor 所做的更改。您能否在代码后台注册一些 JavaScript,以便在异步调用完成时调用 jscolor 的 init 方法?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接