在回发时保持页面内 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 的滚动位置的主要内容,如果未能解决你的问题,请参考以下文章