How To Maintain Scroll Position When Paging Or Sorting A WebGrid

4.56 (9 votes)

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: 23570

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

Ghazanfar 30/01/2016 06:43
In response to Getting Started with ASP.NET MVC 5 using Visual Basic
Nice working. Please keep it up to convert csharp code into vb.net. Its very helpful for vb...

sara 29/01/2016 09:39
In response to Simple Login and Redirect for ASP.NET and Access
Hi there, I am trying to validate and check for inputs entered. When I don't enter any inputs and...

Martin Thatcher 28/01/2016 17:28
In response to MVC 5 with EF 6 in Visual Basic - Advanced Entity Framework Scenarios
A small typo I think. In the code section that begins Function Index(ByVal SelectedDepartment As As...

Suresh_thefame 28/01/2016 08:03
In response to Sessions and Shopping Carts
Helpful....

Andrey Kurdyumov 28/01/2016 05:47
In response to ASP.NET 5: Uploading files with ASP.NET MVC 6
@Lee IFormFile has OpenReadStream(): Stream method...

Alisa 27/01/2016 18:37
In response to A Better Way To Export Gridviews To Excel
Thanks for this example! I am also asking about the date fields having to be re-formatted when the a...

Dan Buckley 27/01/2016 00:47
In response to What ASP.NET Can And Cannot Do
New to all things programming, this was very helpful and clear. Please write more....

satyabrata 26/01/2016 16:16
In response to Request.Form Is Empty When Posting To ASPX Page
Thank you....

david sanchez 26/01/2016 09:51
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Thanks! This line " <img src="~/images/@Model.FilePaths.First(f => f.FileType == alt="" />" an...

Bryon 25/01/2016 15:06
In response to Windows Authentication With ASP.NET Web Pages
Was hoping this would help solve the issues I'm having. Then I saw the dates and new it was too old....