65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (12投票s)

2006年11月8日

CPOL

2分钟阅读

viewsIcon

118742

downloadIcon

1379

一个可滚动面板,在回发后保留其滚动位置。

After postback before restoring scroll position

Scroll position restored

引言

通常,我们会将一个 GridView 包装在一个设置了“overflow:scroll”样式的面板中,并期望用户滚动并选择一个 GridView 项目进行操作。问题是,每当页面回发时,所选项目将不可见,因为面板的滚动位置已被重置。

在我们的最新项目中,我们需要这种功能,但没有找到类似的东西,所以我们决定自己编写它。结果是“StatefulScrollPanel”,一个自定义控件,可以在回发后保留其滚动位置。

背景

基本上,我们只需要一些基本的 JavaScript 知识,以及对 asp:Panel 自身两个方法的简单重写。我们从两个隐藏字段开始,这些字段伴随我们的控件,其目的是跟踪面板(div)的 scrollTopscrollLeft 属性。这些属性以及跟踪控件滚动位置的方法,在我们控件渲染之前被渲染,因此我们重写了 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]InputIdScroll[X|Y]InputValueTraceMethod 属性是用于减少我们必须编写的代码的辅助工具。请查看控件的代码以了解它们的定义。

现在我们只需要在 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 页面中,并设置其 WidthHeight 属性

<cc1:StatefullScrollPanel ID="StatefullScrollPanel1" 
        runat="server" Width="250px" height="105px">
Panel elements go here           
</cc1:StatefullScrollPanel>

请注意,我们不必显式设置溢出样式,因为控件会负责处理。另外请注意,我们可以在同一页面上使用任意数量的控件,因为为每个控件实例生成的代码都是唯一的。我们使用 Firefox 2.0 和 IE 6.0 对代码进行了测试,并且似乎工作正常。

© . All rights reserved.