一个“有状态”的可滚动面板






4.86/5 (12投票s)
一个可滚动面板,在回发后保留其滚动位置。
引言
通常,我们会将一个 GridView
包装在一个设置了“overflow:scroll”样式的面板中,并期望用户滚动并选择一个 GridView
项目进行操作。问题是,每当页面回发时,所选项目将不可见,因为面板的滚动位置已被重置。
在我们的最新项目中,我们需要这种功能,但没有找到类似的东西,所以我们决定自己编写它。结果是“StatefulScrollPanel
”,一个自定义控件,可以在回发后保留其滚动位置。
背景
基本上,我们只需要一些基本的 JavaScript 知识,以及对 asp:Panel
自身两个方法的简单重写。我们从两个隐藏字段开始,这些字段伴随我们的控件,其目的是跟踪面板(div
)的 scrollTop
和 scrollLeft
属性。这些属性以及跟踪控件滚动位置的方法,在我们控件渲染之前被渲染,因此我们重写了 Render
(HtmlTextWriter
) 方法。由于我们希望控件在设计时能够正常显示,因此如果处于设计模式,我们只需委托给父控件。
protected override void Render(HtmlTextWriter writer)
{
if (DesignMode)
{
base.Render(writer);
return;
}
/*
* Hidden inputs to persist scroll position(s)
*/
writer.Write("<input type='hidden' name='" +
ScrollXInputId + "' id='" +
ScrollXInputId + "' value='" +
ScrollXInputValue + "'/>");
writer.Write("<input type='hidden' name='" +
ScrollYInputId + "' id='" +
ScrollYInputId + "' value='" +
ScrollYInputValue + "'/>");
//Trace method that populates the hidden inputs
writer.Write("<script language='Javascript'>function " +
TraceMethod + "{" + GetElementAccessor(ScrollXInputId) +
".value = " + GetElementAccessor(ClientID) +
".scrollLeft;" + GetElementAccessor(ScrollYInputId) +
".value = " + GetElementAccessor(ClientID) +
".scrollTop;}" + "</script>");
//Delegate core rendering to momma
base.Render(writer);
}
GetElementAccessor(String)
方法以及 Scroll[X|Y]InputId
、Scroll[X|Y]InputValue
和 TraceMethod
属性是用于减少我们必须编写的代码的辅助工具。请查看控件的代码以了解它们的定义。
现在我们只需要在 OnLoad(EventArgs)
事件期间将跟踪方法注册到我们的控件,并且设置滚动位置
protected override void OnLoad(EventArgs e)
{
//To enable scrolling in the first place
base.Style.Add(HtmlTextWriterStyle.Overflow, "scroll");
//Register our trace method
base.Attributes.Add("onScroll", TraceMethod);
//On start up set scroll position(s) to the existing one
Page.ClientScript.RegisterStartupScript(GetType(), AdjustScriptKey,
GetElementAccessor (ClientID) + ".scrollLeft = " +
ScrollXInputValue + ";" +
GetElementAccessor(ClientID) + ".scrollTop = " +
ScrollYInputValue + ";",
true);
base.OnLoad(e);
}
就是这样!
使用代码
使用该控件就像使用 asp:Panel
控件本身一样简单。我们将它放到我们的 aspx 页面中,并设置其 Width
和 Height
属性
<cc1:StatefullScrollPanel ID="StatefullScrollPanel1"
runat="server" Width="250px" height="105px">
Panel elements go here
</cc1:StatefullScrollPanel>
请注意,我们不必显式设置溢出样式,因为控件会负责处理。另外请注意,我们可以在同一页面上使用任意数量的控件,因为为每个控件实例生成的代码都是唯一的。我们使用 Firefox 2.0 和 IE 6.0 对代码进行了测试,并且似乎工作正常。