65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 jQuery/jTemplate 的高效通用分页控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (2投票s)

2011年5月5日

CPOL

3分钟阅读

viewsIcon

24898

downloadIcon

429

一个使用 jQuery/jTemplate 的简单分页控件

pager1.gif

引言

我开发的这个分页控件具有以下特性

  1. 它可以与任何 ASP.NET 数据绑定控件(如 RepeaterGridView 等)一起使用。
  2. 它具有非常好的可伸缩性、高效性,并且对数据库友好。
  3. 它非常容易实现和理解。

这是主要思路

首先是此控件的数据库部分。所有的技巧都在这里。我使用了一个 Repeater 控件作为数据绑定控件,我的分页控件将在此基础上工作。但它可以在任何数据绑定控件上工作。例如,绑定此 repeater 控件的查询输出如下

pagerDB.gif

该 repeater 控件每页显示 5 条记录。目前,这个“记录数”是在逻辑中硬编码的。AddressID 字段是数字类型,并且是主键。基本上,我只在客户端存储每页的第一个 AddressId

因此,对于上面的查询,我会在客户端保存以下起始 AddressID

AddressID = 859 (Page# 1)
AddressID = 15460 (Page# 2)
AddressID = 20017 (Page# 3)
AddressID = 25816 (Page# 4)
AddressID = 27652 (Page# 5)

现在,当通过单击“下一页/上一页”按钮或通过下拉列表选择更改页面索引时,jQuery-AJAX 会在数据库上触发一个查询,传递起始 AddressID。它检索以提供的 AddressID 开头的 5 条记录。这是一个例子

[WebMethod]
public static List<RepeaterData> getRepeaterData(int nStartAddressID)
{
    List<RepeaterData> _RepeaterData = new List<RepeaterData>();
    SqlDataReader reader = null;
    DataTable dt = new DataTable();
    using (SqlConnection conn = new SqlConnection())
    {
        conn.ConnectionString = ConfigurationManager.ConnectionStrings
				["ConnStr2"].ConnectionString;
        using (SqlCommand cmd = new SqlCommand())
        {
            //Instead of Dynamic SQL , please use StoredProc for better design.
            //The SqlParameter will protect against any SQL injection 
            //as well as the strong int data-type for the variable nStartAddressID.
            cmd.CommandText = "SELECT TOP (5) AddressID, AddressLine1, 
				City, PostalCode " +
                              "FROM [AdventureWorks].[Person].[Address] " +
                              "WHERE AddressLine1 like '105%' " +
                              "and AddressID >= @AddressID " +
                              "ORDER BY AddressID";
            cmd.Parameters.Add("@AddressID", SqlDbType.Int).Value = nStartAddressID;
            cmd.Connection = conn;
            StringBuilder sb = new StringBuilder();
            conn.Open();
            reader = cmd.ExecuteReader();
            dt.Load(reader);
            conn.Close();
        }
    }
    foreach (DataRow dr in dt.Rows)
    {
        RepeaterData lp = new RepeaterData();
        lp.AddressID = int.Parse(dr["AddressID"].ToString());
        lp.AddressLine1 = dr["AddressLine1"].ToString();
        lp.City = dr["City"].ToString();
        lp.PostalCode = dr["PostalCode"].ToString();
        _RepeaterData.Add(lp);
    }
    return _RepeaterData;
}

在这个例子中,我使用了动态 SQL,但为了更好的设计,请尝试使用 StoredProc 代替。在这种情况下,SqlParameter 将防止任何 SQL 注入。请注意,变量 nStartAddressID 是一个 int,这也防止了各种注入攻击。

这里需要注意的是,在第一次 PageLoad 时,我绑定了 RepeaterDropdownlist,并从代码后端设置了 JavaScript 变量。一旦页面加载完成,所有操作都是通过 jQuery AJAX 使用 jTemplate 进行的。没有回发。
由于 Repeater 本身不发出任何 HTML,因此在 AJAX 调用完成后,jTemplate 可以轻松地替换 Repeater 的 HTML。

在最初的第一次 pageLoad 中,我使用了一个稍微不同的查询来获取前 5 行。

SELECT ROW_NUMBER () OVER (ORDER BY AddressID) AS RowNumber, _
AddressID, AddressLine1, City, PostalCode 
FROM [AdventureWorks].[Person].[Address] where AddressLine1 _
like '105%' ORDER BY AddressID;   

您可以使用带有 SqlParameterStoredProc 来使其免受注入攻击。 我这里只是试图演示这个概念。

正如您所看到的,我在我的 DataView 中获得了行号,并使用它来抓取前 5 条记录。 但是,在任何后续分页操作中,我都会使用起始 addressID 来获取相关的 5 条记录。 这就是我的意思。

在客户端,初始 pageLoad 时,页面编号和相应的起始 AddressID 是这样存储的。

var js1=[{"PagerNums":1,"AddressID":859},
{"PagerNums":2,"AddressID":15460},{"PagerNums":3,"AddressID":20017},
{"PagerNums":4,"AddressID":25816},{"PagerNums":5,"AddressID":27652}] 

正如您所看到的,我只需要跟踪当前页面所在的页面编号。 因此,当单击“上一页/下一页”按钮或更改下拉列表选择时,我会从当前页码中找出起始 AddressID,并将该 AddressID 作为参数提供给 AJAX DB 调用。

function UpdatePrevNextClick() {
    $.ajax({
        type: "POST",
        url: "PagerRepeater4.aspx/getRepeaterData",
        data: "{ 'nStartAddressID': '" + CurAddrID + "' }",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (data) {
            $('#RptPager').setTemplateURL('JTemplates/PagerTemplate.htm');
            $('#RptPager').processTemplate(data.d);
            HidePrevNextButton();
            UpdateDDL();
        }
    });
}

分页操作主要取决于数据绑定控件所在的当前页码。 分页有 3 个触发器,即 - 单击“下一页”按钮、单击“上一页”按钮或从下拉列表中选择页码。

让我们详细了解一下当用户从下拉列表中选择任何页码时的情况。

分页器中的下拉列表包含所有唯一的页码。
因此,当用户选择任何所需的页码时,我会从客户端存储的 JS 数组中找出相应的起始 AddressID

这是代码

<script type="text/javascript">
        var Totalpages = 0;
        $(document).ready(function () {
            var dropDownList1 = $('select[id$=ddl1]');
            Totalpages = dropDownList1[0].length;
            $('.b1').html(dropDownList1[0].length);
            HidePrevNextButton();

            dropDownList1.change(function (e) {
                CurPageNum = this.value;
                CurAddrID = js1[CurPageNum-1].AddressID;
                UpdatePrevNextClick();
            });
        });
    </script>

一旦我获得了起始 Address ID,我就通过 jQuery AJAX 异步触发查询,如上所述。 当页面的相关部分刷新时,我总是验证是否有必要显示/隐藏“上一页/下一页”按钮。 当加载第一页时,“上一页”按钮会被隐藏,类似地,当隐藏最后一页时,“下一页”按钮会被隐藏。

这就是全部。 感谢阅读。

历史

  • 2011-05-05: 版本 1
© . All rights reserved.