How To Maintain Scroll Position When Paging Or Sorting A WebGrid

This snippet is one in a series showing how to use jQuery to enhance the behaviour of a Web Pages WebGrid. This example shows how to maintain scroll position on the page when paging or sorting the WebGrid.

The problem with the default behaviour of the WebGrid is that when you have AJAX paging and sorting enabled, the user is taken to the top of the page when they click a paging or sorting link. That's because the sorting and paging links are generated with an href value of #, which effectively means "this page", and invariably takes the user to the top of the page because there is no fragment identifier after the # sign. While not wanting to get into a debate about the merits of using anchors when there is no destination, the solution in this case is to provide a fragment identifier, and this is relatively easily accomplished using jQuery. A fragment identifier is added to a URL after the # sign and should correspond with an element with a matching name attribute value.

As with other snippets in this series, this example makes use of the SQL CE 4.0 version of the Northwind database. It assumes that you have a layout page that references jQuery and includes a RenderSection call to an optional section named "script":

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />

        <title>@Page.Title</title>
        <script src="@Href("~/scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>

        <link href="@Href("~/styles/site.css")" rel="stylesheet" />
        @RenderSection("script", required: false)
    </head>

    <body>
        @RenderBody()
    </body>
</html>

The sample page gets data from the database, specifies some columns and an AJAX update container. It includes a loop that runs 30 times, and adds an empty paragraphs each time, which pushes the WebGrid below the bottom of most screens. This forces the scroll bar so that the effectiveness of the solution can be tested. Just before the WebGrid itself, a named anchor has been added. It has been given an identifier of "grid-anchor". The last part of the page is the jQuery. This is examined after the code:

@{
    Page.Title = "Maintain scroll position";
    var db = Database.Open("Northwind");
    var query = "SELECT * FROM Customers";
    var data = db.Query(query);
    var columns = new[]{"CustomerID", "CompanyName", "ContactName", "Address", "City", "Country", "Phone"};
    var grid = new WebGrid(data, ajaxUpdateContainerId: "grid", columnNames: columns);
}
<h1>Maintain Scroll Position</h1>
@for(var i = 1; i <= 30; i++){
    <p>&nbsp;</p>
}
<a name="grid-anchor"></a>
<div id="grid">
    @grid.GetHtml(    
        tableStyle : "table",
        alternatingRowStyle : "alternate",
        headerStyle : "header"
    )
</div>
@section script{
<script type="text/javascript">
    $(function(){
        $('th a, tfoot a').live('click', function(){
            $(this).attr('href', '#grid-anchor');
        });
    });
</script>    
}

The sorting and paging links appear in the thead and tfoot elements of the grid. The jQuery targets anchor elements in the thead and tfoot only, and alters their href value to include a fragment identifier - grid-anchor, which ensures that when the links are clicked, the user is navigated back to the named anchor position, thus maintaining scroll position. The click event handler is bound to the links using the live command, which ensures that all future links are affected - essential when the target elements are replaced during an AJAX partial update.

A demo containing the source code is available here.

 

Date Posted:
Last Updated:
Posted by:
Total Views to date: 21815

3 Comments

- reav

timesaver! thx!

- wmeyer

Thanks, exactly what I needed.
To make it so the scroll position doesn't change at all you could lose the "grid-anchor" anchor and change the js line to this: $(this).attr('href', 'javascript:void(0)');

- Mike

@wmeyer

The following also works without named anchors:

$(function(){
$('th a, tfoot a').live('click', function(){
return false;
});
});

Recent Comments

Semil 7/1/2015 7:03 AM
In response to iTextSharp - Drawing shapes and Graphics
I have created a rectangle using above methode. Now I want to add a text in the center of this How I...

Satyabrata Mohapatra 6/30/2015 6:12 PM
In response to Reading Excel Files Without Saving To Disk In ASP.NET
Ahh.....this is awesome. Happy to see after a long time you wrote a article on web form :D...

Marty 6/30/2015 7:16 AM
In response to Posting Data With jQuery AJAX In ASP.NET Razor Web Pages
Mike, you're the Man! Another great article. So incredibly helpful. I'm definitely going to buy your...

Rohan 6/30/2015 5:32 AM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Very good and helpful tutorial. Thanks. Just wanted to know what would be the max file size limit we...

Fernando 6/30/2015 1:59 AM
In response to Programmatically accessing data from DataSource controls
What if I want to pass parameters natively using the DataSourceSelectArguments object, instead of be...

pankaj 6/29/2015 3:13 PM
In response to How to retain carriage returns or line breaks in an ASP.NET web page
very nice i'm use this in my code thank you.... ...

Mike 6/29/2015 2:22 AM
In response to MVC 5 with EF 6 in Visual Basic - Sorting, Filtering and Paging
This is the first example that I have found that works....

Marty 6/28/2015 4:57 AM
In response to Posting Data With jQuery AJAX In ASP.NET Razor Web Pages
Mike, what if I don't want to render back the text to the browser, but I want to send it some other...

Mike 6/27/2015 4:00 PM
In response to Migrating Classic ASP To ASP.NET Razor Web Pages Part One- Razor Syntax And Visual Basic
have you used any of the code converters to convert classic asp to c#? If so, which one do you have...

deepan 6/27/2015 12:49 PM
In response to How To Send Email In ASP.NET MVC
Your article is very very useful for me...thanks for giving this article ...this is very simple to u...