Resetting Scroll Position When Using MaintainScrollPositionOnPostback
By Scott Mitchell
Introduction
ASP.NET 2.0 added a number of built-in client-side enhancements that were missing from earlier versions. Many of these
new features were detailed in an earlier article here on 4Guys, Client-Side
Enhancements in ASP.NET 2.0. One of the least undocumented yet most helpful client-side enhancement, in my opinion, is
MaintainScrollPositionOnPostback.
As its name implies, MaintainScrollPositionOnPostback
ensures that the browser's scroll position is maintained
across postbacks. Without MaintainScrollPositionOnPostback, when a user visits a web page that is "taller" than
the browser window, they have to scroll down to see the content further down on the page. If the user then clicks on a Button
or performs some other action that causes a postback, the browser reloads the page and, by default, returns to the home
scroll position at the top of the page, requiring the user to scroll back down to the location they were viewing when the
postback occurred. To have the user's scroll position remembered across postbacks, simply set
MaintainScrollPositionOnPostback to True, which can be done on a page-by-page basis or applied to all pages
by configuring this option through Web.config.
While MaintainScrollPositionOnPostback makes it easy to keep the visitor at the same scroll position across
postbacks, there are scenarios where you may not want to return the user to their scroll position on postback, but
instead return them to the top of the page. One such example is when displaying a pageable grid. When the user edits a
record, you would want to keep them at the same scroll position, but when they change the page or delete a record, you
may want to reset their scroll position to the top on postback. In this article we will examine a way to override the
behavior of MaintainScrollPositionOnPostback on a case-by-case basis. Read on to learn more!
A Review of MaintainScrollPositionOnPostback
Before we can look at how to optionally reset the scroll position on postback when using MaintainScrollPositionOnPostback,
we need to first examine how MaintainScrollPositionOnPostback works underneath the covers. The Client-Side
Enhancements in ASP.NET 2.0 article gives a pretty thorough explanation of the client-side script emitted by
MaintainScrollPositionOnPostback, and I encourage you to read this article in its entirety. Let's sum up
the most germane parts here.
A page that has MaintainScrollPositionOnPostback set to True adds two hidden form fields to the rendered markup.
These form fields - __SCROLLPOSITIONX and __SCROLLPOSITIONY - track the vertical and horizontal
scroll positions across postbacks:
In addition to the above form fields, when MaintainScrollPositionOnPostback is set to True the page also
emits script that invokes the WebForm_SaveScrollPositionOnSubmit() function when the form is submitted.
WebForm_SaveScrollPositionOnSubmit() sets the current browsers X and Y scroll positions to the
__SCROLLPOSITIONX and __SCROLLPOSITIONY hidden form fields right before the browser submits
the form. When the postback occurs, then, the browser's scroll values are sent in the form fields.
From the Internet.com eBook Library: Navigating Your IT Career
A career in information technology usually has its share of
ups and downs. Download this Internet.com eBook to learn
where the jobs are in IT, how to negotiate a salary, and
helpful advice on job security and how to deal with a layoff.
Join Internet.com now to download! http://www.devx.com/ebook/Link/34938
Interested in placing your TEXT AD HERE? Click Here
On postback, the ASP.NET page adds a call to the client-side function WebForm_RestoreScrollPosition(), which
returns the browser's scroll position to the X and Y coordinates specified by the __SCROLLPOSITIONX and __SCROLLPOSITIONY
form fields (which were assigned the browser's scroll position before the postback ensued). Consequently, the browser's
scroll position is maintained across postbacks. The diagram below illustrates this interaction graphically.
Resetting the Scroll Position
There are a couple of techniques for resetting the scroll position on postback. The simplest and most blunt approach is
to programmatically disable MaintainScrollPositionOnPostback on the page when you want to reset the scroll
position. For example, imagine that you had a Button Web control on the page that, when clicked, should revert the scroll
position to the top of the page. In the Button's Click event handler you could simply set
Page.MaintainScrollPositionOnPostback to False. This will disable the MaintainScrollPositionOnPostback
functionality, reverting the scroll position to the top.
The problem with this ham-fisted approach is that it turns off MaintainScrollPositionOnPostback for subsequent
postbacks as well. That is, after clicking the Button and turning off MaintainScrollPositionOnPostback, imagine
that the user then causes a postback through some other means, and that postback should maintain the scroll position.
Since MaintainScrollPositionOnPostback was disabled, the scroll positions are no longer recorded on postback
so the scroll position is not maintained.
Rather than turn off MaintainScrollPositionOnPostback, a more elegant solution is to inject a bit of
client-side script that resets the values of __SCROLLPOSITIONX and __SCROLLPOSITIONY sent from
the server to 0. This reset needs to happen before the browser calls the WebForm_RestoreScrollPosition()
function. This can be accomplished by using the ClientScript.RegisterStartupScript
method. RegisterStartupScript adds a chunk of JavaScript to the end of the page (right before the closing
</form> element).
When MaintainScrollPositionOnPostback is set to True and the page has been posted back, the
Page class calls RegisterStartupScript in the Render stage, which injects the following markup:
As you can see, the WebForm_SaveScrollPositionOnSubmit() function is called prior to posting back, and the
WebForm_RestoreScrollPosition() function is called on load. What we need to do is inject script before these
function calls that resets __SCROLLPOSITIONX and __SCROLLPOSITIONY to 0. User "guinness" provides
the script to reset the __SCROLLPOSITIONX and __SCROLLPOSITIONY hidden form fields in a post
to microsoft.public.dotnet.framework.aspnet
titled Reset Scroll Position (modified slightly by myself
for readability):
function ResetScrollPosition()
{
var scrollX = document.getElementById('__SCROLLPOSITIONX');
var scrollY = document.getElementById('__SCROLLPOSITIONY');
In order to reset the scroll position, we need to add the above JavaScript to the rendered page's output and then call it
before the call to WebForm_RestoreScrollPosition(). The following code adds a function (ResetScrollPosition)
to the outputted markup and then injects a line of script that invokes this function. The server-side code uses the
RegisterClientScriptBlock method
to register the ResetScrollPosition function, which adds the function to the top of the form.
As noted earlier, RegisterStartupScript adds a call to ResetScrollPosition at the bottom of the
page.
The code for the server-side ResetScrollPosition() method follows. This code, and a complete working demo,
is available for download at the end of this article.
Private Sub ResetScrollPosition()
If Not ClientScript.IsClientScriptBlockRegistered(Me.GetType(), "CreateResetScrollPosition") Then
'Create the ResetScrollPosition() function
ClientScript.RegisterClientScriptBlock(Me.GetType(), "CreateResetScrollPosition", _
"function ResetScrollPosition() {" & vbCrLf & _
" var scrollX = document.getElementById('__SCROLLPOSITIONX');" & vbCrLf & _
" var scrollY = document.getElementById('__SCROLLPOSITIONY');" & vbCrLf & _
" if (scrollX && scrollY) {" & vbCrLf & _
" scrollX.value = 0;" & vbCrLf & _
" scrollY.value = 0;" & vbCrLf & _
" }" & vbCrLf & _
"}", True)
'Add the call to the ResetScrollPosition() function
ClientScript.RegisterStartupScript(Me.GetType(), "CallResetScrollPosition", "ResetScrollPosition();", True)
End If
End Sub
To reset scroll position on postback, simply call the server-side ResetScrollPosition() method from the
appropriate event handler (be it the Click event handler of a Button, the PageIndexChanged event
of the GridView, or some other event). Doing so results in a page with the following rendered markup:
Note the inclusion of the ResetScrollPosition() JavaScript function at the top of the form and its call at
the bottom of the form. As you can see, the __SCROLLPOSITIONX and __SCROLLPOSITIONY hidden form
fields have non-zero values, but the call to ResetScrollPosition() sets them back to 0 before the
WebForm_RestoreScrollPosition() method is called. You can rest assured that ResetScrollPosition()
will always be called first so long as the server-side code that generates the script is called before the Page's Render
event. All postback-related event handlers occur prior to the Render event in the Page's lifecycle.
The download at the end of this article includes the complete source code and a working version of this concept.
In the demo, all pages have their MaintainScrollPositionAcrossPostback properties set to True (via
a Web.config setting). The demo includes a page with a pageable and editable GridView showing 25 records per
page. If you scroll down a ways and edit a record, the scroll position in maintained. If you click the Button titled
"Maintain Position on Postback" at the bottom of the page, the position is maintained. There is another button at the bottom
of the page named "Reset Position on Postback", and this Button's Click event handler injects the script to
reset the scroll position. Furthermore, the GridView's PageIndexChanged event handler also resets the scroll
position so that moving from one page to another in the GridView returns the user to the top of the page on postback.
Conclusion
In this article we looked at how to use MaintainScrollPositionOnPostback, but selectively reset the scroll
position on certain postbacks. The technique involves setting the __SCROLLPOSITIONX and __SCROLLPOSITIONY hidden form
values to 0 on postback prior to the page calling WebForm_RestoreScrollPosition().