在回发时保持页面内 div 的滚动位置

Posted

技术标签:

【中文标题】在回发时保持页面内 div 的滚动位置【英文标题】:Maintain scroll position of a div within a page on postback 【发布时间】:2010-11-08 20:06:52 【问题描述】:

我在一个 aspx 页面中有一个 div,溢出设置为自动。 div 的内容是动态创建的,由链接按钮列表组成。

<div id="div1" style="overflow: auto; height: 100%;">
.....
</div>

当我在 div 中向下滑动并单击任何链接按钮时,页面重新加载会丢失 div 内的滚动位置并将我带到 div 的顶部。有什么办法可以防止这种情况发生吗?

请注意,这是针对页面内的 div 的。 Page.MaintainScrollPositionOnPostBack() 不起作用。

【问题讨论】:

【参考方案1】:

正如 Jeff S 提到的处理这种情况的一种方法是使用 javascript 来跟踪 div 的滚动位置,并且每次页面加载时都会将滚动位置重置为之前的值。

这里有一些示例代码:

<html>
<body onload="javascript:document.getElementById('div1').scrollTop = document.getElementById('scroll').value;">
    <form id="form1" runat="server">
    <input type="hidden" id="scroll" runat="server" />
    <div id="div1" style="overflow: auto; height: 100px;" onscroll="javascript:document.getElementById('scroll').value = this.scrollTop">
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        ...........<br />
        <asp:LinkButton ID="LinkButton1" runat="server" Text="test2"></asp:LinkButton>
    </div>
    <asp:LinkButton ID="LinkButton2" runat="server" Text="test1"></asp:LinkButton>
    </form>
</body>
</html>

实际上,我不会将 javascript 直接放在元素中,而这只是一个示例。您也可以将滚动位置存储在 cookie 中。

【讨论】:

【参考方案2】:

最简单的方法是将控件包装在 UpdatePanel 中。

【讨论】:

【参考方案3】:
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

[ParseChildren(true, "Content")]
public class ScrollSaverPanel: WebControl

    [TemplateInstance(TemplateInstance.Single)]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ITemplate Content  get; set; 

    private HiddenField HiddenField  get; set; 

    protected override HtmlTextWriterTag TagKey
    
        get
        
            return HtmlTextWriterTag.Div;
        
    

    protected override void OnInit(EventArgs e)
    
        HiddenField = new HiddenField();

        var metaContainer = new WebControl(HtmlTextWriterTag.Div);
        metaContainer.Controls.Add(HiddenField);
        metaContainer.Style.Add(HtmlTextWriterStyle.Display, "none");

        Controls.Add(metaContainer);

        var contentContainer = new WebControl(HtmlTextWriterTag.Div);
        Controls.Add(contentContainer);

        Content.InstantiateIn(contentContainer);

        this.Style.Add(HtmlTextWriterStyle.Overflow, "auto");
        this.Attributes.Add("onscroll", string.Format("javascript:document.getElementById('0').value = this.scrollTop;", HiddenField.ClientID));

        base.OnInit(e);
    

    protected override void OnPreRender(EventArgs e)
    
        ScriptManager.RegisterStartupScript(this, this.GetType(), "setscroll", string.Format("javascript:document.getElementById('0').scrollTop = '1';", this.ClientID, HiddenField.Value), true);
        base.OnPreRender(e);
    

用法:

<general:ScrollSaverPanel runat="server">
    <Content>
        <stwrw:Group runat="server" ID="rootGroup"/>
    </Content>
</general:ScrollSaverPanel>

因为有些人不想使用更新面板来保存滚动位置... :)

【讨论】:

【参考方案4】:

一种方法是在 div 的 onscroll 事件中捕获来自 scrollLeft 和 scrollTop 属性的值。将这些值保存在隐藏的文本框中。在回发时,使用文本框中的值重置属性。

【讨论】:

【参考方案5】:

按下链接按钮时会发生什么?回发过程中会进行哪些处理?

根据对这些问题的回答,您可能想要调查完全摆脱回发并纯粹在客户端执行必要的操作。

(我目前正在为客户执行这种转换。)

【讨论】:

按下链接按钮时,它会填充页面上的图形控件。看起来在客户端执行它似乎是最好的方法

以上是关于在回发时保持页面内 div 的滚动位置的主要内容,如果未能解决你的问题,请参考以下文章

从更新面板异步回发后保持滚动位置

asp.net sessionID 在回发时更改?

如何避免在回发时从 asp.net 重复输入?

jQuery填充的Gridview在回发时丢失数据

在回发时,如何向验证摘要添加错误消息?

asp .net背景图像在回发时闪烁