ASP.NET DataList控件中的无限滚动





5.00/5 (4投票s)
像 Facebook 新闻源或 Twitter 推文一样的无限滚动
无限滚动并不是什么难事,例如Facebook的新闻流或Twitter的推文,当用户到达页面底部时,新闻或推文会更新。实际上,客户端脚本会检查容器的滚动位置,如果位置在底部,脚本会从服务器请求内容并更新容器。在这里,容器是一个DIV
标签,命名为holder
,并设置了一些样式标签height
、width
和overflow.holder
,这些样式位于DataList
中。
Holder的CSS样式
<style type="text/css">
#holder {width: 1900px; height:200px;overflow:auto; }
</style>
在这里,我使用了Northwind
数据库的Products
表来演示本文中的无限滚动,并使用了一个Handler
页面。 首次加载页面时,DataList
中包含10条记录,请看下面的示例:
if (!IsPostBack)
{
DataClass data = new DataClass();
DataList1.DataSource = data.FirstTenRecords();
DataList1.DataBind();
}
并且在客户端,我将当前项目计数设置为10
,将下一个项目计数设置为0
。
var current=10;
var next=0;
然后调用JavaScript中的函数来加载下一个内容,这无非就是通过AJAX调用服务器,即使用一个包含start和next的查询字符串请求Handler
页面。 下面的图像显示了客户端的请求URL,我使用了Firebug来显示请求。
让我们看看loadNext
var loadNext = function () {
next = current + 10;
$.ajax({
url: "Handler.ashx?start=" + current + "&next=" + next,
success: function (data) {
$("#DataList1").append(data);
}
});
current = current + 10;
};
在调用Handler
页面之前设置next
,然后在将current
设置为current+10
之后。
next = current + 10;
current = current + 10;
为了从特定的行号获取数据,我使用了一个存储过程,它将返回我的数据。 我想发送位置的数字,如果我发送start=10&next=20
,它将从数据库返回第10行到第20行的数据。
USE [Northwind]
GO
/****** Object: StoredProcedure [dbo].[ProductPages]
Script Date: 11/28/2011 12:03:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ProductPages]
(
@start int,
@next int
)
AS
BEGIN
SELECT ProductID,ProductName,UnitPrice FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY ProductID,ProductName,UnitPrice) NUM,
* FROM Products
) A
WHERE NUM >@start AND NUM <=@next
END
现在让我们看看它是如何工作的。 所有的工作都取决于holder的滚动函数。 脚本检查容器的滚动位置是否在底部,如果是,则调用loadNext()
函数。
$(document).ready(function () {
$("#holder").scroll(function () {
if ($(this)[0].scrollHeight -
$(this).scrollTop() == $(this).outerHeight()) {
loadNext();
}
});
});
Handler
页面就像一个aspx页面一样简单。 它调用一个类文件DataClass
,DataClass
是一个简单的类文件,用于减少Handler
页面中的大量代码。 它调用DataLayer
并从数据库返回数据,在进行一些格式化处理后,将其填充到DataList
中,并将其写入响应。
public void ProcessRequest(HttpContext context)
{
string startQstring = context.Request.QueryString["start"];
string nextQstring = context.Request.QueryString["next"];
//null check
if ((!string.IsNullOrWhiteSpace(startQstring)) &&
(!string.IsNullOrWhiteSpace(nextQstring)))
{
//convert string to int
int start = Convert.ToInt32(startQstring);
int next = Convert.ToInt32(nextQstring);
//setting content type
context.Response.ContentType = "text/plain";
DataClass data = new DataClass();
//writing response
context.Response.Write(data.GetAjaxContent(start, next));
}
}
只有一个类文件。 但是我将类放在该文件中。
DataClass
- Handler页面上包含两个函数,我们正在调用第一个函数
GetAjaxContent(start,end)
,它从数据库返回记录 - 第二个函数在
Page_Load
事件中加载数据 提供
- 从web.config提供
SqlConnection
DBHelper
- 数据层请看
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
/// <summary>
/// Summary description for DataClass
/// </summary>
///
public class DataClass
{
public DataClass()
{
}
/// <summary>
/// return rows depend on position
/// if you need 10th to 20th you need to pass start=10 and end=20
/// </summary>
/// <returns>
/// database start position of one row
/// database end position of one row
/// </returns>
public string GetAjaxContent(int start, int end)
{
string result = string.Empty;
//adding sp params with values in Dictionary entry.
Dictionary<string,> keyValPair = new Dictionary<string,object>();
keyValPair.Add("@start", start);
keyValPair.Add("@next", end);
DBHelper DBHelper = new DBHelper();
//passing the Stored Procedure name and keyvalue pair
DataTable dataTable = DBHelper.GetTable("ProductPages", keyValPair);
if (dataTable.Rows.Count > 0)
{
for (int i = 0; i < dataTable.Rows.Count; i++)
{
result += string.Format(@"<table>
<tbody>
<tr>
<td style="width: 50px; ">{0}</td>
<td style="width: 400px; ">{1}</td>
<td style="width: 150px; ">{2}</td>
</tr>
</tbody>
</table>", dataTable.Rows[i][0].ToString(), dataTable.Rows[i][1].ToString(),
dataTable.Rows[i][2].ToString());
}
}
//this string is going to append on Datalist on client.
return result;
}
/// <summary>
/// function to bind data on page load
/// </summary>
/// <returns />
public DataTable FirstTenRecords()
{
Dictionary<string,object> keyValPair = new Dictionary<string,object>();
keyValPair.Add("@start", 0);
keyValPair.Add("@next", 10);
DBHelper DBHelper = new DBHelper();
DataTable dataTable = DBHelper.GetTable("ProductPages", keyValPair);
return dataTable;
}
}
/// <summary>
/// return sqlconnection string from web.config file
/// </summary>
public class Provider
{
public static SqlConnection GetConnection()
{
return new SqlConnection(ConfigurationManager.AppSettings["SqlConnectionString"]);
}
}
/// <summary>
/// Data layer
/// </summary>
public class DBHelper
{
public DBHelper()
{ }
SqlConnection con;
SqlCommand cmd;
SqlDataAdapter adapter;
public DataTable GetTable(string SPName, Dictionary<string,object> SPParamWithValues)
{
DataTable dataTable = new DataTable();
try
{
con = Provider.GetConnection();
//open DB connection
con.Open();
cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
cmd.CommandText = SPName;
foreach (KeyValuePair<string,object> paramValue in SPParamWithValues)
{
cmd.Parameters.AddWithValue(paramValue.Key, paramValue.Value);
}
adapter = new SqlDataAdapter(cmd);
adapter.Fill(dataTable);
}
finally
{
//close connection string
con.Close();
}
return dataTable;
}
}