在页面的回发中保持一个div的滚动位置

12

我有一个包含overflow属性设置为auto的div元素的aspx页面。该div元素的内容是动态创建的,包含一系列链接按钮。

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

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

请注意,这是针对页面内的一个div。 Page.MaintainScrollPositionOnPostBack()无效。

5个回答

16

正如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中。


6
最简单的方法是将控件包装在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>

由于有些人不想仅为了保存滚动位置而使用UpdatePanel... :)


1

一个方法是在 div 的 onscroll 事件中捕捉 scrollLeft 和 scrollTop 属性的值。将这些值保存在隐藏的文本框中。在 post back 时,使用文本框中的值重置属性。


0
当链接按钮被按下时会发生什么?在 postback 过程中会发生什么处理?
根据这些问题的答案,您可能希望彻底摆脱 postback 并纯粹地在客户端执行必要的操作。
(我目前正在为客户执行此类转换。)

当链接按钮被按下时,它会填充页面上存在的图形控件。似乎在客户端执行这个操作是最好的方法。 - Nikhil

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