ASP.NET UpdatePanel问题使用级联DropDownLists维护页面滚动位置

时间:2013-06-05 17:27:30

标签: asp.net updatepanel ajaxcontroltoolkit maintainscrollpositionon

我真的很感激这个问题的一些帮助。我已经搜索了SO和谷歌寻找这个问题的解决方案,并没有发现任何100%的工作。这是我的问题(请关注我如何设置页面的描述):

我有一个包含在母版页中的页面。此页面使用UpdatePanel中的AjaxControlToolkit TabContainer。每个TabPanel加载不同的用户控件,每个用户控件可以包含1:M输入表单,根据用户是否想要在控件中添加/编辑数据来显示。所有这些功能都很有效,但有时这些表单在视口中不在视图范围内。

为了最大限度地减少用户必须执行的滚动量,我使用PageRequestManager实现了一个jQuery动画事件处理程序。基本上我正在做的是调用ShowForm服务器端方法,然后构建一些JavaScript并将其注入到endRequest的页面中。这是服务器端代码:

private void ShowForm(bool pShowForm) {
    fsAdd.Visible = pShowForm;

    if (pShowForm) {
        LoadScript(FocusOnFormScript("control_client_id"), "control_client_id");
    }
}

protected void DropDownList_OnSelectedIndexChanged(object sender, EventArgs e) {
    //SelectedIndexChanged processing.
    MaintainFocusOnControl(KeepFocusOnFormScript("control_client_id"), "control_client_id");
}

private void LoadScript(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "focusControl_" + pControlId, pScript, true);
}

private void MaintainFocusOnControl(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "maintainFocus_" + pControlId, pScript, true);
}

/// <summary>
/// Scrolls to the form when it is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string FocusOnFormScript(string pControlId) {
    string script = @"
    function FocusOnForm() {
        var offset = $('#" + pControlId + @"').offset();
        $('html, body').animate({ 
            scrollTop: offset.top+200,
            scrollLeft: offset.left+200}, 
            'slow', 
            'easeOutQuart'
        );
        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(FocusOnFormCaller);
    }
    prm.add_endRequest(FocusOnFormCaller);
    function FocusOnFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            FocusOnForm();
        }
    }";
    return script;
}

/// <summary>
/// Scrolls to the form when it is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string KeepFocusOnFormScript(string pControlId) {
    string script = @"
    function KeepFocusOnForm() {
        var offset = $('#" + pControlId + @"').offset();
        window.scrollTo(offset.left+500, offset.top+500); //just jump to the position; scrolling not needed

        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(KeepFocusOnFormCaller);
    }
    prm.add_endRequest(KeepFocusOnFormCaller);
    function KeepFocusOnFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            KeepFocusOnForm();
        }
    }";
    return script;
}

此代码在99%的时间内都很有效。对于我需要级联DropDownLists的特定表单,会出现1%的问题。当DropDownList1被选中时,DropDownList2被正确填充,但页面的滚动位置丢失,DropDownList2的视图被移动到视口的最底部(还有另一个列表和表单,我在下面的表格下面)现在描述)。

我尝试了很多东西,包括:

  • 不同的 maintainScrollPositionOnPostBack 设置
  • PageRequestManager._scrollPosition = null
  • beginRequest 中存储 scrollTop 并将其设置为 endRequest
  • 在单独的endRequest中使用 window.scrollTo(xPos,yPos)
  • 使用 document.documentElement.scrollTop = yPos
  • jQuery的.scrollTop(yPos)

我觉得奇怪的是,如果我设置了一个调用window.scrollTo或document.documentElement.scrollTop的手动链接,它就可以了。我也可以使用已经注册的jQuery animate事件处理程序,然后在UpdatePanel刷新后页面滚动到顶部,然后再次向下滚动。如果我用window.scrollTo或document.documentElement.scrollTop替换animate代码,它就不起作用。

1 个答案:

答案 0 :(得分:0)

我通常做的是将scrollPos存储在隐藏的文本框中,当页面通过回发更新时,在rending之前从文本框中获取值,然后通过一些javascript滚动到屏幕的那一部分......