ASPAlliance.com : The #1 ASP.NET Developer Community : How to Maintain Scroll Position in a DIV
ASPAlliance.com : The #1 Active Server Pages .NET Community The #1 ASP.NET Community
Search   Search

Subscribe   Subscribe

Powered by ORCSWeb Hosting


Site Stats


Powered By ASP.NET
 
Featured Sponsor

Featured Columnist


Featured Book
Professional ASP.NET
Professional ASP.NET

Find Prices
Read Review
Sample Chapter


New! asp.netPRO

We publish our articles in the standard RSS format.

Powerful .NET Email Component

Code Sharing Software
<- Old Dog, New Tricks Printer Friendly Version 

Maintain Scroll Position in any Page Element

By Jim Ross

[Demo]  [Download Source Code]

By now, most avid ASP.NET developers know how to create a scrolling DataGrid or DataList by enclosing the data control within a <div> tag that looks something like this:
<div style="OVERFLOW:auto; WIDTH:100%; HEIGHT:120px">

This will cause a vertical scrollbar to appear whenever the content enclosed within the <div> is taller than 200px. A horizontal scrollbar will also appear if the content is wider than the available width. The user can then scroll the contents of the div to see the part of the DataGrid or DataList that interests them. Unfortunately for this method, when there is a postback for some reason—perhaps the user clicked the “Select” button on a row in the enclosed grid—the <div> resets the scroll position to the top, left and the user must re-scroll down to the row they were working on. See the Demo for an example. Try scrolling the top grid down a few rows, then click the "Select" button to see what we mean here.

What this article will show you

Clearly it would be desirable to be able to retain, or at least re-set the <div>’s scroll position after a postback. That is what this article will show you a method to accomplish. Since I work in a corporate environment where IE is the mandated browser, I decided to implement this capability as an IE “behavior”. It should not be difficult to adapt this for other browsers that support the necessary aspects of the DHTML model.

The Behavior File

Here is a behavior file named ScrollPos that implements the behavior:
ScrollPos.htc 
<PUBLIC:ATTACH EVENT=ondocumentready ONEVENT="elementLoad()" />
<PUBLIC:PROPERTY NAME="scrollPos" />
<PUBLIC:PROPERTY NAME="persistID" />

// DHTML behavior for scrollable DIV
// (or other scrollable element) 
//
// allows element to maintain scroll position within
// the DIV across postbacks. 

<script language="javascript">
    function elementLoad() { 
        element.scrollTop = scrollPos; 
        element.attachEvent("onscroll", saveScroll); 
    }
    
    function saveScroll() { 
        element.document.all[persistID].value =  event.srcElement.scrollTop; 
    } 
</script> 

To use the behavior you must supply values for the two properties, scrollPos and persistID. You do this when you attach the behavior to a page element, as shown in the example below.

scrollPos is used to specify the initial vertical scroll position of the element (and to restore the scroll position on postbacks). Typically it is set to point to the value of the other property, persistID, which must contain the the ID of a hidden input field that will persist the scroll position across postbacks.

Note that this behavior can be attached to as many elements on a page as desired, but each element will require its own separate, unique hidden field.

How does it work?

Notice the first line of the behavior, PUBLIC ATTACH EVENT. This causes the behavior to attach itself to the “ondocumentload” event of the page, and when that event fires the specified behavior method, elementLoad, is called. This bootstrap is necessary to get the In elementLoad, the behavior first sets its attached element’s scrollTop property to the specified value. Typically on initial page load this will be 0.

Then the behavior attattaches itself to the element’s “onscroll” event, so that whenever the user scrolls the element, the specified method (saveScroll) will be called. When called, saveScroll merely saves the current scrollTop value for the attached element into the hidden field whose ID was specified in the behavior’s persistID property.

Here's an example of how to use the behavior with a <div> element that is being used to scroll a DataGrid:

 <divpersistID="<%=  
    saveScrollPos.UniqueID%>"scrollPos="<%= saveScrollPos.value %>"
    style="BEHAVIOR: url(<%=ResolveURL(‘../Includes/ScrollPos.htc’); %>); 
    OVERFLOW: auto; WIDTH: 100%; HEIGHT: 150px" >

    <input id="saveScrollPos" type="hidden" runat="server" NAME="saveScrollPos">

    <asp:datagrid . . . put your grid, list, etc. here >
</div>


The Demo shows the behavior in action. Try scrolling the bottom grid list down a few lines, then click "Select". The grid should retain its position after the postback.

The method is self-supporting. No additional code is needed, so long as the page has viewstate enabled. Notice how the persistID and scrollPos properties both utilize the same hidden field. Whatever value has been saved into the hidden input field, saveScrollPos in this example, will be automatically specified to the behavior’s scrollPos property when the page is returned to the client.

Limitations and caveats

Limitation: The behavior, as presented here, only maintains vertical scroll position. If you also need to maintain a horizontal scroll position, you will need to add properties for the id of a field to store the horizontal position and pass it back to the control, and modify the methods to also save and set scrollLeft for the element.

Caveat: This code, as shown, will only work correctly if your page is using C#. The reason is the way the url for the BEHAVIOR must be coded, with the URL itself included in single quotes within the style tag which is delimited by double quotes. If you try to use this code on a page that is using VB, you will get an error, because VB will see the single quote within the URL as the beginning of a comment, and treat the rest of the line as a comment. You can overcome this by reversing the use of single and double quote marks, but both VS.NET and WebMatrix will then see your style block as violating “well formed XHTML” and change the outer single quote back to a double quote. So far, no power this writer has yet observed on, above or below earth can make them behave differently . Arrrggggghhhhh.

One workaround for this problem is to simply define the URL of the behavior as a string value elsewhere on the page:

<% Dim scrollPosURL As String = “../Includes/ScrollPos.htc” %>

And now you can simply refer to the string within your style tag:

Style=”BEHAVIOR: url(>% ResolveURL( scrollPosURL) %>); . . .

This method is also very useful if you will be using the behavior in multiple places on the page, as it allows you to define the URL in only one place.

[Demo]  [Download Source Code]

<- Old Dog, New Tricks Printer Friendly Version 
 Copyright © 2000-2003 ASPAlliance.com  Page Rendered at 11/21/2009 11:36:57 AM