ASP.net Postback - 滚动到特定位置

30
我有一个ASP.net WebForms页面,在页面顶部有很多内容。它有一个链接按钮,点击后会刷新页面并显示页面的另一部分。当页面刷新时,我想设置焦点并滚动到页面的这个部分。
我尝试过以下代码:
txtField.Focus()
在我的代码后台,我设置了焦点并尝试滚动到底部,但它会立即回滚到顶部。文本框仍然是焦点所在,但屏幕位置在顶部。链接位于屏幕顶部,这导致回传。我想要滚动到屏幕底部,虽然它能够短暂地做到,但马上又会滚回到顶部。
我已经尝试过设置:
Page.MaintainScrollPositionOnPostback = false;

但这似乎也没有帮助。

有没有办法强制让它跳转到特定位置?在使用按钮或链接按钮进行回发时,是否可能向URL添加锚标签?


不,链接在屏幕顶部。我想要滚动到屏幕底部。当我进行postback时,由于我在控件上调用了Focus()方法,它会短暂地这样做,但是出于某种原因,它会立即滚动回到顶部。 - Dismissile
使用客户端脚本来设置焦点。这也会处理滚动到控件的问题。 - Bala R
似乎也不起作用。就像我的页面上有些东西会导致它每次滚动到顶部一样。我想不出来。当我回传时,是否可以在我的URL中添加一个锚标签? - Dismissile
ASP.NET Web Forms中的滚动控件已经损坏,无法正常工作。MaintainScrollPositionOnPostback是这个有缺陷的系统的一部分。你需要在客户端自己设置滚动条,并且要有足够的延迟来避免竞争条件...或者覆盖Microsoft的ScriptResource代码。我最终决定覆盖他们的WebForm_AutoFocus函数是使页面不跳动的唯一方法。 - Paul Kienitz
9个回答

38

使用一个id属性(锚标签)来区分页面的不同部分怎么样?在postback后,您可以动态填充Response.Redirect("yourpagewithanchortagrefernece")。 - Theomax
最终只能使用UpdatePanel了,尽管我很讨厌它们 :( - Dismissile
对我来说没有用,看看下面的ClientScript.RegisterStartupScript(..)解决方案,这个对我有用。 - Patrick from NDepend team
是的,Page.MaintainScrollPositionOnPostBack 应该 这样做...但它没有。 - Paul Kienitz

34

如果您已经有了一个锚点位置,可以使用以下代码:

Page.ClientScript.RegisterStartupScript(this.GetType(), "hash", "location.hash = '#MOVEHERE';", true);

8
@Dismissile 我认为这应该被标记为答案。您无需从头重新加载页面(因此代码仅在发生某些后台事件时才能应用),而且已接受的答案未被使用,并且被声明为与所要求的完全相反。 - James
2
这对我有用,设置为 Page.MaintainScrollPositionOnPostBack = false; 在特定实例中(因为我的页面通常设置为true) - fortboise
这可能会遇到竞态条件。 - Paul Kienitz

9
在您的情况下,我建议您保留Page.MaintainScrollPositionOnPostBack的默认值,并使用纯JavaScript滚动功能。
function scrollToDiv()
{
    document.getElementById('yourDiv').scrollIntoView();
}

并且在页面启动时以1毫秒的小延迟调用它(纯JavaScript)

setTimeout(scrollToDiv, 1);

最后,在C#代码中使用RegisterStartupScript调用它(js在页面全部加载后执行):
ScriptManager.RegisterStartupScript(Page, typeof(Page), "ScrollToADiv", "setTimeout(scrollToDiv, 1);", true);

这样做可以绕过任何ASP自动滚动。


1
尝试这个。
protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.IsPostBack) {
            string targetId = Page.Request.Params.Get("__EVENTTARGET");
            Page.ClientScript.RegisterStartupScript(this.GetType(), "focusthis", "document.getElementById('" + targetId + "').focus()", true);

        }
    }

虽然这可能回答了作者的问题,但缺少一些解释性词语和/或文档链接。裸露的代码片段没有一些附加的文字是不太有帮助的。您也可能会发现如何编写好答案非常有用。请[编辑]您的答案 - 来自审查 - Nick

0

我尝试了Matthieu Charbonnier的答案,但除非我添加了

" window.scrollTo = function () { };" 

正如http://gnidesign.blogspot.com.au/2011/06/how-to-maintain-page-scroll-on-postback.html所建议的

我创建了一个辅助方法,它在Chrome、FireFox和IE上均可工作。

public static void ScrollToControl( Page page, string clientId, bool alignToTop)
 {
     //NOTE: if there are more than one call on the page, first one will take preference
     //If we want that last will take  preference, change key from MethodBase.GetCurrentMethod().Name to anchorName
     //recommended in http://gnidesign.blogspot.com.au/2011/06/how-to-maintain-page-scroll-on-postback.html              
     String script = " window.scrollTo = function () { };" + Environment.NewLine;
     script += String.Format("document.getElementById('{0}').scrollIntoView({1});" , clientId, alignToTop.JSToString());
     page.ClientScript.RegisterStartupScript(TypeForClientScript(), MethodBase.GetCurrentMethod().Name, script, true );
     //return script;
 }
 public static string JSToString(this bool bValue)
 {
     return bValue.ToString().ToLower();
 }

使用getElementById('{0}').scrollIntoView比location.hash更简单,因为您不需要添加额外的锚点元素。

参数alignToTop非常方便,可以指定您想要在屏幕顶部还是底部显示控件。


0

我有

<asp:MultiView ID="mvAriza" runat="server">
      <asp:View ID="View14" runat="server"> 
         ............ .......
      </asp:View>
</asp:MultiView>

在 *.aspx 页面上。并在 *.aspx.cs 页面上的按钮单击事件中。
Page.SetFocus(mvAriza.ClientID);

它运行得很好。


0

Page.MaintainScrollPositionOnPostback = true 看起来运行良好。


0

这是一个与ASP.NET控件相关的功能,可以自动滚动到所需的Div位置。

您可以在任何地方调用此函数,并下载JavaScript文件。

在客户端单击时,使用OnClientClick="return scrollGrid()"。

function scrollGrid1() { $('html,body').animate ( { scrollTop: $('#Div1').offset().top }, 'slow' ) }


0

虽然不太适合您的情况,但也可以使用虚拟自定义验证器,将要滚动到的验证器设置为无效,然后执行

DummyCustomValidator.SetFocusOnError = true;

在我的情况下,我实际上正在使用带有异步回发和多个以编程方式显示/隐藏的面板的页面验证器。由于某些字段仅在MyLogicalParent.Visible = true时才需要,并且如果在其他控件中给出特定答案,例如当在CheckBoxList中选择“其他”时,在TextBox上使用RequiredFieldValidator,因此我有很多逻辑来处理页面验证。在所有常规方法中设置滚动位置都很痛苦。
我还使用RegisterStartupScript来处理在异步回发改变页面垂直尺寸时保持当前滚动位置的问题。
    <script type="text/javascript">
        $(document).ready(function () {
            var windowHeight = $(document)[0].documentElement.clientHeight;    /*This is the height of the viewable browser area.*/
            var scrolledPosition = $(window)[0].scrollY;                       /*This is the number of Pixels the Window is currently scrolled to.*/
            var scroll = windowHeight + scrolledPosition;                       /*This should be the same as $(window).scrollTop() */
            /*If the amount scrolled + the height of the window is Less than or equal to the total height of the page (past the viewable client window)*/
            if ($(window).scrollTop() + getWindowSize()[1] <= getDocHeight()) {
                /*Move the morescroll div to the bottom of the page... -34 is the height of the div plus a small bottom margin.*/
                $("#morescroll").offset({ top: windowHeight - 34 });
            }
        })

        /*This is the total height of the document including the area past the viewable client window.*/
        function getDocHeight() {
            var D = document;
            /*The Largest of these six numbers is the total doc height. */
            return Math.max(
                D.body.scrollHeight, D.documentElement.scrollHeight,
                D.body.offsetHeight, D.documentElement.offsetHeight,
                D.body.clientHeight, D.documentElement.clientHeight
            );
        }

        /*This is the width and height of the Viewable Browser area.*/
        function getWindowSize() {
            var myWidth = 0, myHeight = 0;
            if (typeof (window.innerWidth) == 'number') {
                //Non-IE
                myWidth = window.innerWidth;
                myHeight = window.innerHeight;
            } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
                //IE 6+ in 'standards compliant mode'
                myWidth = document.documentElement.clientWidth;
                myHeight = document.documentElement.clientHeight;
            } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
                //IE 4 compatible
                myWidth = document.body.clientWidth;
                myHeight = document.body.clientHeight;
            }
            return [myWidth, myHeight];
        }

        //This sets a transparent div <div id="morescroll" class="scrollMinder"> with the text "Scroll down for more." to the bottom of the viewable page. 
        $(window).scroll(
            function () {
                var windowHeight = $(document)[0].documentElement.clientHeight;
                var scrolledPosition = $(window)[0].scrollY;
                var scrll = windowHeight + scrolledPosition;
                document.getElementById('<%= HF_LastScrolled.ClientID %>').value = scrolledPosition;
                var docHeight = $(document)[0].documentElement.scrollHeight;
                /*if we are scrolled to within 60 pixels from the bottom of the document, hide the indicator so it doesn't cover the footer.*/
                if ($(window).scrollTop() + $(window).height() >= $(document).height() - 60) {
                    $("#morescroll").hide();
                }
                /*if we scroll back above 60 pixels from the bottom of the document, show the indicator and set the top of the div to -34 pixels.*/
                else if ($(window).scrollTop() + getWindowSize()[1] <= getDocHeight()) {
                    $("#morescroll").show();
                    $("#morescroll").offset({ top: scrll - 34 });
                }
            });
</script>

     <%-- This stores the Y scroll location.--%>
        <asp:HiddenField ID="HF_LastScrolled" runat="server" />
        <div id="morescroll" class="scrollMinder">
            <span class="spanMinder">Scroll down for more.</span>
        </div>





 private string LastScrolled = "";

    protected void Page_PreRender (object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(LastScrolled))
                {
                    LastScrolled = "0";
                }
                if (string.IsNullOrEmpty(scrollPosition))
                {
                    sb.Clear();
                    sb.AppendLine("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);");
                    sb.AppendLine("function EndRequestHandler(sender, args) {");
                    sb.Append("scrollTo(0, ").Append(LastScrolled).Append(");");
                    sb.AppendLine("}");
                    sb.AppendLine("function load() {");
                    sb.AppendLine("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);");
                    sb.AppendLine("}");
                    cs.RegisterStartupScript(GetType(), "ScrollToLastPosition", sb.ToString(), true);
                    scrollPosition = "ScrollToLastPosition";
                }
                if (!string.IsNullOrEmpty(scrollPosition))
                {
                    ScriptManager.RegisterStartupScript(this, GetType(), scrollPosition, sb.ToString(), true);
                }
            }

    protected void Page_Load (object sender, EventArgs e)
            {
              LastScrolled = HF_LastScrolled.Value;
              Page.MaintainScrollPositionOnPostBack = false;
            }

   protected void SetScrollToLastPosition ()
            {
                sb.Clear();
                sb.AppendLine("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);");
                sb.AppendLine("function EndRequestHandler(sender, args) {");
                sb.Append("scrollTo(0, ").Append(LastScrolled).AppendLine(");");
                sb.AppendLine("}");
                sb.AppendLine("function load() {");
                sb.AppendLine("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);");
                sb.AppendLine("}");
                cs.RegisterStartupScript(GetType(), "ScrollToLastPosition", sb.ToString(), true);
                scrollPosition = "ScrollToLastPosition";
                string tempstring = sb.ToString();
                ScriptManager.RegisterStartupScript(this, GetType(), scrollPosition, sb.ToString(), true);
            }

protected void SetScrolltoPositionY (int y)
            {
                sb.Clear();
                sb.AppendLine("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);");
                sb.AppendLine("function EndRequestHandler(sender, args) {");
                sb.Append("scrollTo(0, ").Append(y).AppendLine(");");
                sb.AppendLine("}");
                sb.AppendLine("function load() {");
                sb.AppendLine("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);");
                sb.AppendLine("}");
                cs.RegisterStartupScript(GetType(), "ScrollTo-0-" + y.ToString(), sb.ToString(), true);
                scrollPosition = "ScrollTo - 0-" + y.ToString();
                string tempstring = sb.ToString();
                ScriptManager.RegisterStartupScript(this, GetType(), scrollPosition, sb.ToString(), true);
            }

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