Infinite Scroll with a Repeater

One of the requirements for a project I have been working on lately is that paging of data is not allowed.  The solution so far had been just to output all the records to a GridView control which was fine until the data behind the application started to grow.  Once where only 50, 100, 200 records were being written out we are now getting 1000+ which, as you might expect, was not ideal for page rendering.

So I’ve looked at introducing paging back into the project but in an infinite scrolling capacity.

What is Infinite Scrolling?

In short it’s paging without the page numbers.

The best example I can give here is the experience you get when browsing Google images.  When you get to the bottom of the list the page dynamically refreshes and presents you with the next set (or page) of images related to the search you have carried out. There’s no clicking of page numbers or navigation to another page, the next set of images just get appended on to the bottom of the page you are currently viewing.

Why should I use it?

In my opinion it fully depends on the circumstances in which you are presenting the data.  It’s certainly a great way of keeping the user interested in your page and doesn’t strike fear into the users heart as there will never be a visible Page 1 of 100 on your page but it’s entirely up to you.  Infinite scrolling is JavaScript dependent so there will be some users who won’t be able to use it but if your code falls back gracefully (to classic paging for example) then I see no reason not to consider this solution.

Think, for example, if you were developing an online store and you were presenting the user with a list of t-shirts.  Your store may stock 1000 different varieties of t-shirt and from a performance point of view you certainly wouldn’t want to render all 1000 t-shirts and their associated images on page load so you’d probably think that you’ll page the data.  Then you think okay, 20 t-shirts per page seems like a good idea but that’s then 50 pages that your user would have to click through in order to see all of your stock (yes I appreciate that you could provide filters for records per page etc but let’s work on the basis that this is a pretty basic set up).

This is a perfect scenario for infinite scrolling.  You can still get your data back from your database in chunks of 20 products at a time but the user doesn’t have to click through pages.  All he or she needs to do is scroll to the bottom of the list and wait for the next page of t-shirts to be displayed.  

So how do I do it?

Start off be setting your web form up with a repeater and some code behind to do the initial bind e.g.

Markup

<form id="form1" runat="server">
    <div>
        <table id="ProductsTable">
            <thead>
                <tr>
                    <th>Column 1</th>
                    <th>Column 2</th>
                </tr>
            </thead>
            <tbody>
                <asp:Repeater ID="InfiniteScrollRepeater" runat="server" EnableViewState="false">
                    <ItemTemplate>
                        <tr>
                            <td><%#Eval("Column1") %></td>
                            <td><%#Eval("Column2") %></td>
                        </tr>
                    </ItemTemplate>
                </asp:Repeater>
            </tbody>
        </table>
    </div>
</form>

Example Code Behind

Once your markup is ready, jump to the code behind and do your initial server side data bind (you could do this via the client as well but for arguments sake we’ll do the first data bind on the server).

private int PageSize
{
    get { return 100; }
}

protected override void OnInit(EventArgs e)
{
    // Bind the first page of data (pageNumber = 1, pageSize = 100)
    using (DataTable dt = Products.GetProducts(1, PageSize))
    {
        InfiniteScrollRepeater.DataSource = dt;
        InfiniteScrollRepeater.DataBind();
    }
            
    base.OnInit(e);
}

So if you hit F5 now you should see something like this:

Infinite Scroll Initial Server Side Data Bind

This’ll give you the first 100 records bound to your repeater.

Now for the interesting bit. To get your infinite scroll on you need to add a little bit of client side code:

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
    var pageNumber = 1;

    $(document).ready(function () {
        $(window).scroll(function () {
            // Get the current vertical position of the scrollbar.  If it's equal to the height of the document minus the 
            // window height then go get some more data
            if ($(window).scrollTop() == $(document).height() - $(window).height()) {
                // Increment page number and set up the parameters
                pageNumber += 1;
                var params = "{'pageNumber': " + pageNumber + "}";

                // Async post back to the BindDataAsync code behind web method
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/BindDataAsync(pageNumber),
                    data: params,
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data) {
                        if (data != "") {
                            // Take the results from the web service method and append them to the table
                            $('#ProductsTable').append(data.d);
                        }
                    }
                });
            }
        });
    });
</script>

And in the code behind we need to add that BindDataAsync method. Note that this is declared as a WebMethod so that the client side code can get to it:

/// <summary>
/// Marked as a WebMethod so that it's possible for the client script to get access to it.        
/// </summary>
[WebMethod]
public static string BindDataAsync(int pageNumber)
{
    StringBuilder sb = new 

    // Pass in page number and page size as your database call should
    // only return the first (x) records in this case it's page 1, max records 100
    using (DataTable dt = Products.GetProducts(pageNumber, 100))
    {
        foreach (DataRow r in dt.Rows)
        {
            sb.Append("<tr><td>" + r["Column1"].ToString() + "</td><td>" + r["Column2"].ToString() + "</td></tr>");
        }
    }

    return sb.ToString();
}

And with the exception of the call to Products.GetProducts that’s pretty much all you need to get a simple infinite scrolling solution into your ASP.Net web forms project.

I hope you’ve found this useful. The code for this example can be downloaded below.

Download InfiniteScroll Solution

7 Comments Infinite Scroll with a Repeater

  1. Wouter

    Nice article ! thanks for sharing your knowledge, only 1 remark, in the example above u forgotten to add the webmethod in the ajax call url: “Default.aspx/****

    is included in sourcecode, …

    Reply
    1. Craig

      Hi Nitish,

      You should be able to do this with a couple of small amendments to the sample code I provided (Note: I haven’t tested this as I’m in a coffee shop at the moment and don’t have my dev laptop with me). However:

      In the markup add

      <td><%#Eval("ImageSourceColumn") %></td>

      after the last <td>, or wherever you want the image to display. Then amend the WebMethod so that the sb.Append line reads something like

      sb.Append("<tr><td>" + r["Column1"].ToString() + "</td><td>" + r["Column2"].ToString() + "</td><td><img src='" + r["ImageSourceColumn"].ToString() + "' /></td></tr>");
      

      That should work, or hopefully help point you in the right direction.

      Reply
  2. Samjith

    Hi,
    Thanks for the article.
    How can we do the same in the repeaters having itemdatabound event and the content is not table but a block of div elements with datas.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *