如何在更新面板回发后执行JavaScript回调?

72
我正在使用一个 jQuery 提示插件,当用户悬浮在页面上的某些元素时显示帮助提示。
我需要使用 CSS 选择器在页面加载后注册插件事件。
问题是我正在使用 ASP.NET UpdatePanel,在第一次回发后,提示停止工作,因为更新面板替换了页面内容但没有重新绑定 JavaScript 事件。
我需要一种方式在 UpdatePanel 刷新其内容后执行 JavaScript 回调,以便我可以重新绑定 JavaScript 事件以使提示再次正常工作。
有没有什么方法可以做到这一点?
5个回答

169

把你的jQuery代码放在$(document).ready()之内,改为放在

</body>

标签之前。

function pageLoad(sender, args) { 
    ... 
}

pageLoad会在每次同步或异步的postback之后执行。 pageLoad是ASP.NET AJAX中保留的函数名称,用于此目的。$(document).ready()则只在DOM初始准备/加载完成时执行一次。

请参见此ASP.NET AJAX客户端生命周期事件概述


4
谢谢您的回答。我不知道有客户端的pageLoad事件,而它正是我所需要的。问题解决了 :) - tsbnunes
+1 胜利!我之前也不知道这个存在,正是我解决问题所需要的!@Russ Cam,感谢你! - longda
我的页面中有两个更新面板。有没有办法在pageLoad中知道哪个更新面板导致了异步刷新? - empz
1
谢谢伙计,这解决了我的问题,因为我在每个页面上都有一个带有JQuery的更新面板。对我来说,它就像魔法一样起作用。非常感谢。 - Sumit Gupta
@Russ Cam,你的encosia.com链接似乎存在危险。当我尝试访问该页面时,谷歌会发出警告。在此查看警告。 - Hill
显示剩余5条评论

19

页面加载没有起作用。我使用了这个代替:

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);

function pageLoaded() {
}

2
如果你遇到了“Sys id not defined”的错误,那是因为你在脚本管理器加载之前调用了脚本。通常情况下,脚本管理器会在<body>标签中加载,而脚本则在<head>标签中加载。是的,我知道这很奇怪!只需将你的脚本移到页面底部或控件底部,就可以与接受的答案一起正常工作了。 - Piotr Kula

12

这可能远非最优雅的解决方案,但它仍然是一个解决方案:

public class UpdatePanel : System.Web.UI.UpdatePanel
{
    /// <summary>
    /// Javascript to be run when the updatepanel has completed updating
    /// </summary>
    [Description("Javascript to be run when the updatepanel has completed updating"),
        Category("Values"),
        DefaultValue(null),
        Browsable(true)]
    public string OnUpdateCompleteClientScript
    {
        get
        {
            return (string)ViewState["OnUpdateCompleteClientScript"];
        }
        set
        {
            ViewState["OnUpdateCompleteClientScript"] = value;
        }
    }

    protected override void OnPreRender(System.EventArgs e)
    {
        base.OnPreRender(e);
        if(!string.IsNullOrEmpty(this.OnUpdateCompleteClientScript))
            Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID, string.Concat("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, args){for(var panelId in sender._updatePanelClientIDs){if(sender._updatePanelClientIDs[panelId] == '", this.ClientID, "'){", this.OnUpdateCompleteClientScript, "}}});"), true);
    }
}

使用方法如下:

<uc:UpdatePanel OnUpdateCompleteClientScript="alert('update complete');">
    <!-- stuff in here -->
</uc:UpdatePanel>

当然,您需要在webconfig或页面中注册自定义控件才能像这样使用它。

编辑:另外,您看过jquery.live吗?


1
自定义的Update Panel用户控件对我的问题来说有点过头了,但是我不知道jquery.live方法,它可能会起作用并解决我的问题! 但在这种情况下,我认为Russ Cam提出的解决方案更好,我已经尝试过它,效果很好。谢谢你的帮助。 :) - tsbnunes
一定有更简单的方法吧..? - HasanG

0
使用pageLoaded事件并检查回调或后台提交:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(function (sender, args) {
    if (args._panelsUpdated && args._panelsUpdated.length > 0) {
        //callback;
    }
    else {
        //postback;
    }
});

0

如果您想在 UpdatePanel 加载之前和之后执行特定操作,可以像下面这样重写 BeginPostbackRequestEndPostbackRequest

var postbackControl = null;
var updatePanels = null;
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginPostbackRequest);
prm.add_endRequest(EndPostbackRequest);

function BeginPostbackRequest(sender, args) {
    prm._scrollPosition = null;
    postbackControl = args.get_postBackElement();
    postbackControl.disabled = true;
    updatePanels = args._updatePanelsToUpdate;
    // do your stuff
}

function EndPostbackRequest(sender, args) {
    // do your stuff
    postbackControl.disabled = false;
    postbackControl = null;
    updatePanels = null;
}

如果您只想处理由更新面板提供的HTML,则这非常方便。某些操作需要更多资源,如果在pageLoad上处理整个DOM树将会过度杀伤。


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