异步回发后重置滚动位置 - ASP.NET

7
什么是将滚动位置重置到页面顶部的最佳方法,而异步回发后该如何处理? 异步回发是从ASP.NET GridView CommandField列中发起的,并在GridView OnRowCommand中调用了ASP.NET更新面板Update方法。 我目前的应用程序是一个ASP.NET 3.5网站。编辑:我收到了每个人的卓越反馈,并在script标记中使用了PageRequestManager方法,但我的下一个问题是:如何配置它仅在用户单击我的GridView控件中的ASP.NET CommandField时执行? 我页面上有其他按钮执行异步回发,我不想滚动页面到顶部。编辑1:我已经开发出一种解决方案,不需要使用PageRequestManager。 请参见我的后续答案以获取解决方案。
8个回答

17

由于您正在使用UpdatePanels,因此需要连接到ASP.NET AJAX的PageRequestManager

您需要添加一个方法到endRequest事件钩子中:

在异步回发完成并且控件已经返回到浏览器之后引发。

所以您应该有如下代码:

<script type="text/javascript">
  Sys.WebForms.PageRequestManager.getInstance().add_endRequest(pageLoaded);

  function pageLoaded(sender, args) {
     window.scrollTo(0,0);
  }
</script>

在更新请求完成后,这将强制浏览器滚动回页面顶部。

当然,您可以钩入其他事件:

beginRequest // Raised before the request is sent
initializeRequest // Raised as the request is initialised (good for cancelling)
pageLoaded // Raised once the request has returned, and content is loaded
pageLoading // Raised once the request has returned, and before content is loaded
异步回发的优点在于,页面会保持滚动高度而不需要设置MaintainScrollPosition,因为没有发生“完整页面重新加载”,但是在这种情况下您实际上需要那种效果,所以您需要手动创建它。
编辑以响应更新的问题:
好的,所以如果您只需要在某些按钮按下时重置位置,您需要执行以下操作:
首先,钩入BeginRequest而不是/也是:
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);

这是因为在参数(args)中你可以访问到:

args.get_postBackElement().id

以下代码将告诉您启动整个事件的按钮ID-然后您可以在此处检查该值并移动页面,或者将其存储在变量中并在最终请求中查询它-请注意竞争条件等情况,其中用户在原始更新完成前单击另一个按钮。

希望这对你有所帮助-在“使用PageRequestManager事件”上有很多示例。


11
这是将滚动条位置重置为顶部的完美解决方案,使用AJAX
客户端代码
function ResetScrollPosition()
{
    setTimeout("window.scrollTo(0,0)", 0);
}

服务器端代码

ScriptManager.RegisterStartupScript(Page, this.GetType(), "ScrollPage", "ResetScrollPosition();", true);

仅使用window.scrollTo(0,0)将无效。在这种情况下,Ajax将优先执行,因此您必须使用setTimeout函数。


是的,但如果你只想在特定事件发生时,并且只在点击按钮时的特定时间发生这种情况呢? - Jack Marchetti

4

以下是我根据这个源代码开发的解决方案。

ASP.NET Webform

<script language="javascript" type="text/javascript">
   function SetScrollEvent() {
      window.scrollTo(0,0);
   }
</script> 

<asp:GridView id="MyGridView" runat="server" OnRowDataBound="MyGridView_OnRowDataBound">
    <Columns>
        <asp:CommandField ButtonType="Link" ShowEditButton="true" />
    </Columns>
</asp:GridView>

ASP.NET Webform的代码后台

protected void MyGridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
    if(e.Row.RowType.Equals(DataControlRowType.DataRow))
    {
        foreach (DataControlFieldCell cell in e.Row.Cells)
        {
            foreach(Control control in cell.Controls)
            {
                LinkButton lb = control as LinkButton;

                if (lb != null && lb.CommandName == "Edit")
                    lb.Attributes.Add("onclick", "SetScrollEvent();");
            }
        }
    }
}

2
你是否正在使用asp.net AJAX?如果是,客户端库中有两个非常有用的事件beginRequest和endRequest。异步更新时的一个问题是,总页面并不知道你在做什么。beginRequest和endRequest事件允许你在客户端保持滚动位置。你可以在JavaScript中设置一个变量,在beginRequest事件中将其设置为滚动位置,然后在endRequest事件中重置所需元素的scrollTop。我确信以前见过这样的操作,但找不到链接。如果我找到示例,我会发布链接。

2

以下内容摘自本教程:

https://web.archive.org/web/20211020134824/https://aspnet.4guysfromrolla.com/articles/111407-1.aspx

我们将MaintainScrollPositionOnPostback设置为true

然后,如果需要重置滚动位置,请调用该方法:

Private Sub ResetScrollPosition()
If Not ClientScript.IsClientScriptBlockRegistered(Me.GetType(), "CreateResetScrollPosition") Then
   'Create the ResetScrollPosition() function
   ClientScript.RegisterClientScriptBlock(Me.GetType(), "CreateResetScrollPosition", _
                    "function ResetScrollPosition() {" & vbCrLf & _
                    " var scrollX = document.getElementById('__SCROLLPOSITIONX');" & vbCrLf & _
                    " var scrollY = document.getElementById('__SCROLLPOSITIONY');" & vbCrLf & _
                    " if (scrollX && scrollY) {" & vbCrLf & _
                    "    scrollX.value = 0;" & vbCrLf & _
                    "    scrollY.value = 0;" & vbCrLf & _
                    " }" & vbCrLf & _
                    "}", True)

   'Add the call to the ResetScrollPosition() function
   ClientScript.RegisterStartupScript(Me.GetType(), "CallResetScrollPosition", "ResetScrollPosition();", True)
End If
End Sub 

0

我使用一个名为hScrollTop的隐藏输入框,在提交asp.net表单之前进行设置。然后,当页面加载时,根据隐藏输入框的值设置scrollTop。

在新页面上尝试此代码。

<div style="height:500px"></div>

<form id="Form1" runat=server onsubmit="javascript:saveScrollTop();">
    <input type=submit value="Submit" runat=server>
    <input type="hidden" id="hScrollTop" runat=server>
</form>

<div style="height:1000px"></div>

<script language="javascript">
    function saveScrollTop() {
        document.getElementById("<%= hScrollTop.ClientID %>").value = document.body.scrollTop;
        return true;
    }

    window.onload = function() {
        document.body.scrollTop = document.getElementById("<%= hScrollTop.ClientID %>").value;
    }

</script>

0
你设置了页面属性MaintainScrollPosition吗?不确定是否在进行异步后台处理时会有任何不同。
编辑:你可以尝试将焦点设置在页面顶部附近的特定项目上,这可能有所帮助,并且是一种不太正式的解决方法。

我只想在ASP.NET GridView的特定事件中返回页面顶部。我在同一页上有许多其他按钮,我希望它们保持滚动位置。 - Michael Kniskern

0
Page.RegisterStartupScript("MyScript", "<script language=javascript>setTimeout('window.scrollTo(0,0)', 0);</script>");

将上述代码放入您想要让页面返回顶部的函数中。例如,当页面无效时,将其添加到函数中,它将临时添加JavaScript代码以将您带回页面顶部。

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