ASP.NET 頁面回傳後,頁面級滾動條可通過 MaintainScrollPositionOnPostback="true" 保持,但頁面內部 <div> 區域的滾動位置卻會重置。這在長列表、聊天記錄、日誌查看等場景極大地損害用戶體驗。本文提供一組通用的服務端輔助方法,配合客戶端 JavaScript,實現多個 Div 滾動位置的自動保存與恢復。
using System;
using System.Web.UI;
public static class ScrollPositionHelper
{
///
/// 保存指定 Div 的滾動位置到隱藏字段
///
public static void SaveDivScrollPosition(string divIdArray, Page page)
{
string[] divIds = divIdArray.Split(',');
foreach (string divId in divIds)
{
string hiddenFieldName = divId + "__SCROLLPOS";
// 註冊隱藏字段保存上次提交的值
page.ClientScript.RegisterHiddenField(hiddenFieldName, page.Request.Form[hiddenFieldName]);
// 註冊客戶端腳本:onscroll 時寫入隱藏字段
string script = $@"
function saveScrollPosition_{divId}() {{
var el = document.getElementById('{divId}');
if (el) {{
document.forms[0].{hiddenFieldName}.value = el.scrollTop + ',' + el.scrollLeft;
}}
}}
var el = document.getElementById('{divId}');
if (el) el.onscroll = saveScrollPosition_{divId};
";
page.ClientScript.RegisterStartupScript(page.GetType(), "saveScroll_" + divId, script, true);
}
}
///
/// 頁面加載後恢復 Div 滾動位置
///
public static void RestoreDivScrollPosition(string divIdArray, Page page)
{
string[] divIds = divIdArray.Split(',');
string callScript = "";
foreach (string divId in divIds)
{
callScript += $"SetScrollPosition('{divId}');";
}
string script = $"";
page.ClientScript.RegisterStartupScript(page.GetType(), "restoreScroll", script, false);
}
}
放在頁面或引用的 .js 文件中:
function SetScrollPosition(divId) {
var hiddenField = document.forms[0][divId + '__SCROLLPOS'];
var div = document.getElementById(divId);
if (div && hiddenField && hiddenField.value) {
var coords = hiddenField.value.split(',');
div.scrollTop = parseInt(coords[0], 10) || 0;
div.scrollLeft = parseInt(coords[1], 10) || 0;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) return;
// 頁面包含 div1, div2, div3 三個可滾動區域
ScrollPositionHelper.SaveDivScrollPosition("div1,div2,div3", this);
ScrollPositionHelper.RestoreDivScrollPosition("div1,div2,div3", this);
}
PersistDivScrollPosition(ids, page),減少調用複雜度。PageRequestManager 的 endRequest 事件中重新綁定 onscroll 與恢復位置。document.getElementById 而非 document.all,支援現代瀏覽器。