Implementing Continuous Scrolling UI Pattern in ASP.NET
By mv ark
When you have numerous records to show, we have to resort to Paging. There is a better alternative to display voluminous data (especially read only data) while providing a better user experience & also making efficient use of server bandwidth - the Continuous Scrolling or Infinite Scrolling UI Pattern. Read on to know more about how to implement Continuous Scrolling UI Pattern in ASP.NET with a GridView.
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
Popularity (8181 Views)
 |
| Biography - mv ark |
M.V. 'Anil' Radhakrishna is a seasoned developer who enjoys working with Microsoft tools & technologies. He blogs his little discoveries and about Web development tips, tricks and trivia quite regularly. You can find some of his unusual code samples & snippets at his Code Gallery. |
|
Article Discussion: Implementing Continuous Scrolling UI Pattern in ASP.NET
mv ark posted at Saturday, February 28, 2009 5:57 AM
How to set GridView Row properties using Infinite Scrolling
Hi
I have implemented your solution and it works the way it should work
I also tried implementing using DataTable and everything works fine with putting code at runtime
Now my problem is the first column in Gridview is a Image Template Field
In order to use Row_Command property I have to set the index of each image
using code like this
for
(int iRows = 0; iRows < XGrid1.Rows.Count; iRows++)
{
GridViewRow
myRow = XGrid1.Rows[iRows];
ImageButton b = (ImageButton)myRow.Cells[1].FindControl("imgbtnShow");
b.CommandArgument = indexItem.ToString();
//this index keeps track of which image is clicked
indexItem = indexItem + 1;
}
Here in this article we create a StringBuilder and append the table rows to it
I do not know how we could do it using this articl
Thanks for your help
Need Guidence
I am unable to implement this pattern - could you please provide project for download in vb ...
viswa rao replied
to mv ark at Sunday, October 24, 2010 1:29 AM
I could not download Jquery 1.2.6. So I used jquery-1.4.2.min.js
I copied all your code.
After compiling and running it shows a page with empty box with no gridview in it. How I can I debug or find out what is wrong?
Ghawadi replied
to mv ark at Sunday, October 24, 2010 1:29 AM
I tried to implement what is in the article, the grid was loaded with data at the initial load, but when scrolling down nothing happen! I used the jquery.min.js is it possible to upload a sample project?
dev User replied
to mv ark at Sunday, October 24, 2010 1:29 AM
How to handle post back events on scrolling e-g On Scrolling i
render a user control in ashx handler using a html form tag where I have
a asp.net button with click event but on clicking it does not fire
click event except for submitting form and redirect to ashx handler
with white screen.
Has anyone implemented this with post back events like button click ?