If you have used Google Reader, Live Image Search or Wikia Search (the open source search engine), you may have noticed how the Infinite Scrolling
or the Continuous Scrolling UI Pattern works.

UIPatterns explains Continuous Scrolling thus:
In contrast to the Pagination patterns, the Continuous Scrolling pattern has no natural
break. When using pagination patterns, a decision to only show a subset of data
at a time and then let the user request more data if wanted is chosen. With the
Continuous Scrolling, new data is automatically retrieved as the user has scrolled
to the bottom of the page. It thus appears as if the page has no end, as more
data will be loaded and inserted into the page each time the user scrolls to
the bottom of page.
The minimalistic code sample explained here will show how to fetch records asynchronously
on scrolling from a hypothetical Orders table after the first batch is initially
fetched. A Generic Handler (which is similar to an ASPX page but lacks HTML tags)
is used to retrieve records asynchronously and hand it over to the parent page.
So the sample basically consists of the following 2 files which you will have
to copy to a ASP.NET 2.0 Website in VS.NET 2005 or VS.NET 2008 -
FetchOnDemand.aspx
AsyncHandler.ashx
All the JavaScript magic to track when the user reaches the end of the scroll bar
(in this example we simulate DIV scrolling by restricting it's height &
setting overflow:auto style for the DIV tag) is done effortlessly by jQuery, a "JavaScript Library that simplifies HTML document traversing, event handling, animating,
and Ajax interactions for rapid web development".
You can grab the external JavaScript file representing the jQuery library need for
this sample from either of these URLs -
http://code.jquery.com/jquery-latest.js
http://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js
You can copy and place the external JavaScript file in a JS folder under the ASP.NET
2.0 website you create in VS.NET for running this code sample or you may even
choose to reference it directly in the code. The jQuery library will be used
in the parent page (FetchOnDemand.aspx) to trigger fetching of new records dynamically on scrolling to the bottom. The
parent page communicates the unique Id related to the last row that was previously
fetched to a Generic Handler (AsyncHandler.ashx). The Handler in turn returns a batch of new records asynchronously as a HTML table
so that it can be injected at the end of table rendered by the GridView in the
parent page.
Onto the code ...
FetchOnDemand.aspx displays the first 20 records through a GridView. jQuery helps us get the last Order
Id from the last row of the table rendered from the GridView. We pass this as
parameter to the Generic Handler's querystring -
"AsyncHandler.ashx?lastOrderId="
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataSet
ds = new DataSet();
SqlConnection
conn = new SqlConnection("_place_your_connection_string_here");
string _cmdText = "Select TOP 20 OrderID, Convert(Varchar,OrderDate,101) OrderDate, Quantity From
Orders";
SqlDataAdapter
da = new SqlDataAdapter(_cmdText, conn);
da.Fill(ds,
"Orders");
tblOrders.DataSource
= ds;
tblOrders.DataBind();
}
}
</script>
<html
xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dynamic Content
Load On Scroll</title>
<style type="text/css">
body
{
font-family:
Verdana, Arial, Helvetica, sans-serif;
font-size:
11px;
color:
#666666;
}
.divLeft
{
height:
200px;
border:
solid 1px black;
width:
300px;
text-align:
left;
overflow:
auto;
}
.divProgress
{
width:
15%;
background-color:
red;
color:
white;
}
.tblHeader
{
font-weight:
bold;
text-align:
left;
background-color:
gray;
color:
black;
}
td
{
text-align:center;
}
</style>
<script
src="js/jquery-1.2.6.js" type="text/javascript"></script>
<script type="text/javascript">
//following code utilizes jQuery 1.2.6
var prev = 0;
$(document).ready(
//DIV showing the message "Loading..." is hidden initially
//The message will be shown when records are fetched with AJAX
//when user has scrolled to the bottom of the DIV scrollbar
function() {
$(".divProgress").hide();
$(".divLeft").scroll(
function()
{
//triggering point is when the difference of the heights of the TABLE
//and DIV match the DIV's scrollTop value
if ($("#tblOrders").height() - this.scrollTop == $(this).height()) {
//progress bar
$(".divProgress").ajaxStart(function() {
$(this).show();
});
$(".divProgress").ajaxStop(function() {
$(this).hide();
});
//get last Order Id to track next fetch
var OrderIdLast = $("#tblOrders tr:last").children("td:first").html();
//get last table row in order to append the new result set increment
var trLast = $("#tblOrders tr:last");
if (parseInt(OrderIdLast, 10) > parseInt(prev, 10)) {
prev
= OrderIdLast;
//make a async call to fetch the incremental results
$.post("AsyncHandler.ashx?lastOrderId=" + OrderIdLast, function(data) {
if (data != null) {
//append new result set to last row
trLast.after(data);
}
});
}
}
});
});
</script>
</head>
<body>
<h3>This
is a demo to show Continous Scrolling UI Pattern</h3>
<form
id="form1" runat="server">
<div class="divLeft">
<asp:GridView ID="tblOrders" runat="server" AutoGenerateColumns="false" CellPadding="2" Width="100%">
<HeaderStyle
CssClass="tblHeader" />
<Columns>
<asp:TemplateField
HeaderText="Order Id">
<ItemTemplate>
<%#Eval("OrderID")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField
HeaderText="Order Date">
<ItemTemplate>
<%#
Eval("OrderDate")%>
<input
type="hidden" id="htxtOrderId" runat="server" value='<%#Eval("OrderID")%>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField
HeaderText="Quantity">
<ItemTemplate>
<%#Eval("Quantity")%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div
class="divProgress">
Loading....
</div>
</form>
</body>
</html>
AsyncHandler.ashx keeps the weight of the response lighter than an equivalent ASPX page. It takes
a OrderId value & returns the next five records formatted in a HTML table
so that it can be readily appended to the table in the parent view containing
the bigger set of records.
<%@ WebHandler Language="C#" Class="AsyncHandler" %>
using System;
using System.Web;
using System.Text;
using System.Data;
using System.Data.SqlClient;
public class AsyncHandler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
//REMOVE BELOW LINE if you are using it in a real application
//It is here to simulate the delay while fetching results
System.Threading.Thread.Sleep(2000);
//The last OrderId is used to get the next increment
string lastOrderId = Convert.ToString(context.Request.QueryString["lastOrderId"]);
//The PrepareDataSet method stuffs the DataSet into a HTML table
context.Response.Write(PrepareDataSet(lastOrderId));
}
private string PrepareDataSet(string _orderId)
{
System.Data.SqlClient.SqlConnection
conn = new SqlConnection("_place_your_connection_string_here");
string _cmdText =
"Select TOP 10 OrderID, Convert(Varchar,OrderDate,101) OrderDate, Quantity From
Orders Where OrderID >" + _orderId;
SqlDataAdapter
da = new System.Data.SqlClient.SqlDataAdapter(_cmdText, conn);
DataSet
ds = new System.Data.DataSet();
da.Fill(ds,
"Orders");
//The BuildRows method prepares a HTML table & stuffs the resultset into it
return BuildRows(ds.Tables[0]);
}
private string BuildRows(System.Data.DataTable dt)
{
StringBuilder
sb = new StringBuilder();
System.Data.DataRow
dr;
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
sb.Append("<tr class='tblRow'>");
dr
= dt.Rows[i];
for (int j = 0; j < dt.Columns.Count; j++)
{
sb.Append("<td>" + dr[j] + "</td>");
}
sb.Append("</tr>");
}
}
return sb.ToString();
}
public bool IsReusable {
get {
return false;
}
}
}
The Continuous Scrolling UI Pattern is an user-friendly way to display a large number
of records. jQuery makes it easy to manipulate the DOM and dynamically add incremental
results to the initial result set.
References:
Load Content While Scrolling With jQuery
Implementing infinite scrolling with jQuery