asp.net学习_分页的设计
分页是每一个程序员都每天都在打交道的东西,分页.
一年前,刚接触的时候,根本不知道什么叫做分页,后台,xxx说,如果数据过多一次,成千上万条,你一次只看到10-20条,为什么要全部显示呢?当时感觉很震撼,为什么呢?
以下内容是以前的代码(不要扔鸡蛋,我现在看了都有恨不得砸电脑的冲动)
于是我们就用了第一个分页版本,当时,两个实验室的"战士"研究了好久,找到一个存储过程的分页,当时感觉好神奇!找找当时凌乱的分页调用程序:
现在看了都要砸电脑的冲动的东东.....
后来做web,凌乱依旧,web版本的分页程序,
后来才发现一个叫做aspnetpager的控件,发现好强大呀,易用,方便,而且不用写那么复杂的存储过程以及调用,
慢慢的发现,这些控件都是死的,写死的东西,根本没有灵活性,特别是美工做个好看点的分页之类的,只能干瞪眼,要不就按照它的格式做分页样式,这是一个纠结的问题,
既然不灵活,为什么不自己做控件?
后来就自己写分页的用户控件....
不过仍然不够灵活,上网找资料.
发现,手写一个分页类就行了,分页不就是计算页面大小,然后输出页码和连接么?
然后就是这个版本
1: // //记录日志
2: private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
3: //输出的PagerHtml代码
4: public string PagerHtml = "";
5: protected void Page_Load(object sender, EventArgs e)
6: {
7: try
8: {
9: string TypeId = Request["TypeId"];
10: //查询条件
11: string strCondition = "";
12: //字符串注入检测
13: if (!string.IsNullOrEmpty(TypeId) && Tools.IsValidInput(ref TypeId, true))
14: strCondition = "TypeId=" + TypeId;
15:
16: //分页实现
17: var pager = new Common.RupengPager();
18: pager.UrlFormat = "NewsList.aspx?pagenum={n}&TypeId=" + TypeId;
19: pager.PageSize = 30;
20: pager.TryParseCurrentPageIndex(Request["pagenum"]);
21:
22: //分页数据读取
23: newsBLL bll = new newsBLL();
24: DataTable dt = bll.ListByPaginationForView("Time", pager.PageSize, pager.CurrentPageIndex, "1", strCondition);
25:
26: //获取总页数
27: pager.TotalCount = bll.GetVNewsListCount(strCondition);
28: rpData.DataSource = dt;
29: rpData.DataBind();
30:
31: //渲染页码条HTML
32: PagerHtml = pager.Render();
33: }
34: catch (Exception ex)
35: {
36: logger.Error("错误:", ex);
37: }
38: }
效果也就是这样:
前台就是
1: <%@ Page Language="C#" MasterPageFile="~/InfoPage.master" AutoEventWireup="true" CodeFile="NewsList.aspx.cs" Inherits="News_NewsList" Title="新闻列表" %>
2:
3: <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
4: <link href="../css/other.css" rel="stylesheet" type="text/css" />
5: <link href="../css/Pager.css" rel="stylesheet" type="text/css" />
6: </asp:Content>
7: <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
8: <%--GetNewsTypeInfoForNewsByJson--%>
9:
10: <p class="list">
11: <p class="list_title"><h4>新闻列表</h4><span>当前位置:<a href="../Default.aspx">首页</a> > 新闻列表</span></p>
12: <ul>
13: <asp:Repeater ID="rpData" runat="server">
14: <ItemTemplate>
15: <li><a href='ViewNews.aspx?NewsId=<%#Eval("Id") %>'>[<%#Eval("TypeName")%>]<%#Eval("Title")%></a><span><%#Eval("Time")%></span></li>
16: </ItemTemplate>
17: </asp:Repeater>
18: </ul>
19: <p class="page">
20: <p><p class="pager"><%=PagerHtml%></p></p>
21:
22: </p>
23: </p>
24:
25: </asp:Content>
26:
效果图:
这样仍然有一些问题:
为什么一定要后台处理呢?
为什么后台要做这些显示相关的?
后台只负责提供数据,而界面实现,完全应该由js解决......
因此,就有了现在这个版本....
上网研究了一下Jquery pager,然后在他的基础上,该改改,然后就有了现在这个版本,后台只负责提供数据(json格式)
前台负责界面显示
js分页:
1: //Download by http://www.codefans.net
2: //每次只显示5个页码
3: //修改:2012/4/26
4: //tianzhuanghu
5: //http://www.cnblogs.com/mysweet/ 我的博客
6: (function($) {
7: //设定页码方法,初始化
8: $.fn.setPager = function(options) {
9: var opts = $.extend({}, pagerDefaults, options);
10: return this.each(function() {
11: //修改,能够动态设置PageSize
12: pagerDefaults.PageSize=options.PageSize;
13: $(this).empty().append(setPagerHtml(parseInt(options.RecordCount), parseInt(options.PageIndex), options.buttonClick));
14: $('.pager a').mouseover(function() { document.body.style.cursor = "pointer"; }).mouseout(function() { document.body.style.cursor = "auto"; });
15: });
16: };
17: //设定页数及html
18: function setPagerHtml(RecordCount, PageIndex, pagerClick) {
19:
20: var $content = $("<p class=\"pager\"></p>");
21: var startPageIndex = 1;
22: //若页码超出
23: if (RecordCount <= 0) RecordCount = pagerDefaults.PageSize;
24: var PageSize=pagerDefaults.PageSize;
25: //alert(pagerDefaults.PageSize);
26: //末页
27: var endPageIndex = parseInt(RecordCount % parseInt(PageSize)) > 0 ? parseInt(RecordCount / parseInt(PageSize)) + 1 : RecordCount / parseInt(PageSize);
28:
29: if (PageIndex > endPageIndex) PageIndex = endPageIndex;
30: if (PageIndex <= 0) PageIndex = startPageIndex;
31: var nextPageIndex = PageIndex + 1;
32: var prevPageIndex = PageIndex - 1;
33: if (PageIndex == startPageIndex) {
34: $content.append($("<span>首页</span>"));
35: $content.append($("<span>上一页</span>"));
36: } else {
37:
38: $content.append(renderButton(RecordCount, 1, pagerClick, "首页"));
39: $content.append(renderButton(RecordCount, prevPageIndex, pagerClick, "上一页"));
40: }
41: //这里判断是否显示页码
42: if (pagerDefaults.ShowPageNumber) {
43: // var html = "";
44: //页码部分隐藏 只显示中间区域
45: if (endPageIndex <= 5 && PageIndex <= 5) {
46: for (var i = 1; i <= endPageIndex; i++) {
47: if (i == PageIndex) {
48: $content.append($("<span>" + i + "</span>"));
49: } else {
50: $content.append(renderButton(RecordCount, i, pagerClick, i));
51: }
52:
53: }
54:
55: } else if (endPageIndex > 5 && endPageIndex - PageIndex <= 2) {
56:
57: $content.append($("<a>...</a>"));
58: for (var i = endPageIndex - 4; i <= endPageIndex; i++) {
59: if (i == PageIndex) {
60: $content.append($("<span>" + i + "</span>"));
61: } else {
62: $content.append(renderButton(RecordCount, i, pagerClick, i));
63: }
64:
65: }
66: } else if (endPageIndex > 5 && PageIndex > 3) {
67:
68: $content.append($("<a>...</a>"));
69: for (var i = PageIndex - 2; i <= PageIndex + 2; i++) {
70: if (i == PageIndex) {
71: $content.append($("<span>" + i + "</span>"));
72: } else {
73: $content.append(renderButton(RecordCount, i, pagerClick, i));
74: }
75:
76: }
77: $content.append($("<a>...</a>"));
78:
79: } else if (endPageIndex > 5 && PageIndex <= 3) {
80:
81: for (var i = 1; i <= 5; i++) {
82: if (i == PageIndex) {
83: $content.append($("<span>" + i + "</span>"));
84: } else {
85: $content.append(renderButton(RecordCount, i, pagerClick, i));
86: }
87:
88: }
89: $content.append($("<a>...</a>"));
90: }
91: }
92: if (PageIndex == endPageIndex) {
93: $content.append($("<span>下一页</span>"));
94: $content.append($("<span>末页</span>"));
95: } else {
96: $content.append(renderButton(RecordCount, nextPageIndex, pagerClick, "下一页"));
97: $content.append(renderButton(RecordCount, endPageIndex, pagerClick, "末页"));
98: }
99:
100:
101: return $content;
102: }
103: function renderButton(recordCount, goPageIndex, EventHander, text) {
104: var $goto = $("<a title=\"第" + goPageIndex + "页\">" + text + "</a>\"");
105: $goto.click(function() {
106:
107: EventHander(recordCount, goPageIndex,pagerDefaults.PageSize);
108: });
109: return $goto;
110: }
111: var pagerDefaults = {
112: DefaultPageCount: 1,
113: DefaultPageIndex: 1,
114: PageSize:20,
115: ShowPageNumber: true //是否显示页码
116: };
117: })(jQuery);
前台页面显示:
1: <%@ Page Language="C#" MasterPageFile="~/InfoPage.master" AutoEventWireup="true"
2: CodeFile="MasterList.aspx.cs" Inherits="Master_MasterList" Title="大师风采" %>
3:
4: <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
5: <link href="../css/other.css" rel="stylesheet" type="text/css" />
6:
7: <script src="../Admin/scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
8:
9: <script src="../js/jquery-pager-1.0.js" type="text/javascript"></script>
10:
11: <link href="../css/pager.css" rel="stylesheet" type="text/css" />
12:
13: <script type="text/javascript">
14: $(document).ready(function() {
15: //加载PageSize和页码PageIndex
16: GetData(1,1);
17: });
18: function InitPager(RecordCount, PageIndex,PageSize,Data) {
19: $("#Pager").setPager({ RecordCount: RecordCount, PageIndex: PageIndex,PageSize:PageSize, buttonClick: PageClick });
20: //页面数据填充
21: $("#tBodyMaster").empty();
22: $.each(Data,function(key,value){
23: //图片回调(集中请求)
24: var PicSrc="../Admin/FileManage/GetImg.ashx?method=GetMasterPic&type=medium&fileName="+Data[key].Picturepath;
25: var item='<tr><td><a href="'+"#"+'"><img src="'+PicSrc+'" title="'+Data[key].Name+'" alt="'+Data[key].Name+'"/><br/>'+Data[key].Name+'</a></td>';
26: item+='<td class="jianjie"><span>'+Data[key].Introduction+'</span></td>';
27: item+='<td class="adress"><a href="'+"#"+'">'+Data[key].Name+'的主页</a></td></tr>';
28: $("#tBodyMaster").append(item);
29: });
30: };
31: PageClick = function(RecordCount,PageIndex,PageSize) {
32: GetData(PageSize,PageIndex);
33: };
34: //sortField排序字段
35: function GetData(PageSize,PageIndex){
36: $.ajax({
37: url:'../Admin/MasterManage/Data/MasterInfo.ashx?method=SearchMaster',
38: //注意后台分页存储过程的PageIndex是从0开始的,所以这里要-1
39: data:'sortField=Id&sortOrder=desc&pageIndex='+(PageIndex-1)+'&pageSize='+PageSize,
40: success:function(text){
41: var jsonData=$.parseJSON(text);
42: InitPager(jsonData.total, PageIndex,PageSize,jsonData.data);
43: }
44:
45: });
46: }
47:
48: </script>
49:
50: </asp:Content>
51: <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
52: <p class="list">
53: <p class="list_load">
54: <h3>
55: 大师风采</h3>
56: <span><a href="../Default.aspx">首页</a> > 大师风采</span>
57: </p>
58: <p class="ol">
59: <table width="680" border="0" cellpadding="0" cellspacing="0">
60: <thead>
61: <tr>
62: <th width="160">
63: 大师名称
64: </th>
65: <th width="310">
66: 大师简介
67: </th>
68: <th width="210">
69: 大师个人网页
70: </th>
71: </tr>
72: </thead>
73: <tbody id="tBodyMaster">
74:
75: </tbody>
76: </table>
77: </p>
78: <p id="Pager">
79: </p>
80: </p>
81: </asp:Content>
后台则负责数据的提供:
1: /// <summary>
2: /// 搜索调用
3: /// </summary>
4: /// <param name="context"></param>
5: public void SearchMaster(HttpContext context)
6: {
7: //查询条件
8: string key = context.Request["key"];
9: //分页
10: int pageIndex = Convert.ToInt32(context.Request["pageIndex"]);
11: int pageSize = Convert.ToInt32(context.Request["pageSize"]);
12: //字段排序
13: String sortField = context.Request["sortField"];
14: String sortOrder = context.Request["sortOrder"];
15: string strCondition = "";
16: //对搜索内容进行验证
17: if (!Common.Tools.IsValidInput(ref key, false))
18: {
19: return;
20: }
21: else
22: strCondition = masterBLL.ConfirmCondition(key);//判断查询条件
23: masterBLL bll = new masterBLL();
24: //分页数据读取
25: IEnumerable<master> list = bll.ListByPagination(sortField, pageSize, pageIndex + 1, sortOrder == "asc" ? "1" : "0", strCondition);
26: //获取总页数
27: int totalPage = bll.GetCount(strCondition);
28: //JSON 序列化
29: string json = masterBLL.MiniUiListToJson(list, totalPage, "");
30:
31:
32: context.Response.Write(json);
33: }
BLL生成json方法:(这个方法我是代码生成器写成一个模板,然后每次自动生成,免得每次都要写,哈哈哈)
1: /// <summary>
2: /// 专门生成为MiniUi生成json数据(List->json)
3: /// </summary>
4: /// <typeparam name="T">泛型</typeparam>
5: /// <param name="list">实现了Ilist接口的list</param>
6: /// <param name="total">记录总数</param>
7: /// <param name="paramMaxMin">这里放排序的参数例如,string para=""maxAge":37,"avgAge":27,"minAge":24"</param>
8: /// <returns>返回json数据</returns>
9: public static string MiniUiListToJson(IEnumerable<master> masterInfo, int total, string paramMaxMinAvg)
10: {
11: StringBuilder Json = new StringBuilder();
12: Json.Append("{\"total\":"+total+",\"data\":");
13: Json.Append("[");
14: foreach (master Info in masterInfo)
15: {
16: Json.Append("{");
17: Json.Append("\"Id\":\"" + Info.Id + "\"");
18: Json.Append(",");
19: Json.Append("\"Username\":\"" + Info.Username + "\"");
20: Json.Append(",");
21: Json.Append("\"Password\":\"" + Info.Password + "\"");
22: Json.Append(",");
23: Json.Append("\"Name\":\"" + Info.Name + "\"");
24: Json.Append(",");
25: Json.Append("\"Introduction\":\"" + Info.Introduction + "\"");
26: Json.Append(",");
27: Json.Append("\"Isrecommend\":\"" + Info.Isrecommend + "\"");
28: Json.Append(",");
29: Json.Append("\"Isshow\":\"" + Info.Isshow + "\"");
30: Json.Append(",");
31: Json.Append("\"Picturepath\":\"" + Info.Picturepath + "\"");
32: Json.Append(",");
33: Json.Append("\"Sex\":\"" + Info.Sex + "\"");
34: Json.Append(",");
35: Json.Append("\"Nation\":\"" + Info.Nation + "\"");
36: Json.Append(",");
37: Json.Append("\"mobilephone\":\"" + Info.mobilephone + "\"");
38: Json.Append(",");
39: Json.Append("\"Telephone\":\"" + Info.Telephone + "\"");
40: Json.Append(",");
41: Json.Append("\"Email\":\"" + Info.Email + "\"");
42: Json.Append(",");
43: Json.Append("\"QQ\":\"" + Info.QQ + "\"");
44: Json.Append(",");
45: Json.Append("\"Zipcode\":\"" + Info.Zipcode + "\"");
46: Json.Append(",");
47: Json.Append("\"Address\":\"" + Info.Address + "\"");
48: Json.Append(",");
49: Json.Append("\"appreciation\":\"" + Info.appreciation + "\"");
50: Json.Append(",");
51: Json.Append("\"website\":\"" + Info.website + "\"");
52: Json.Append(",");
53: Json.Append("\"Reward\":\"" + Info.Reward + "\"");
54: Json.Append(",");
55: Json.Append("\"BirthDay\":\"" + Info.BirthDay + "\"");
56: Json.Append(",");
57: Json.Append("\"state\":\"" + Info.state + "\"");
58: Json.Append(",");
59: Json.Append("\"state1\":\"" + Info.state1 + "\"");
60: Json.Append(",");
61: Json.Append("\"hit\":\"" + Info.hit + "\"");
62: Json.Append(",");
63: Json.Append("\"rank\":\"" + Info.rank + "\"");
64: Json.Append("}");
65: if(Info != masterInfo.Last())
66: {
67: Json.Append(",");
68: }
69: }
70: Json.Append("]}");
71: return Json.ToString();
72: }
存储过程:一直就用的上网找的,一个非常完美的存储过程:(感觉优化的很好,我做了多次封装,用起来非常方便):
1: USE [czcraft]
2: GO
3: /****** 对象: StoredProcedure [dbo].[pagination] 脚本日期: 04/26/2012 21:04:21 ******/
4: SET ANSI_NULLS ON
5: GO
6: SET QUOTED_IDENTIFIER ON
7: GO
8: CREATE PROCEDURE [dbo].[pagination]
9: @tblName varchar(255), -- 表名
10: @innerJohn varchar(500), --inner john连接的表
11: -- @innerJohnCondition varchar(255), --inner john连接条件
12: @strGetFields varchar(1000) = '*', -- 需要返回的列
13: @fldName varchar(255)='', -- 排序的字段名
14: @PageSize int = 10, -- 页尺寸
15: @PageIndex int = 1, -- 页码
16: @doCount bit = 0, -- 返回记录总数, 非0 值则返回
17: @OrderType bit = 0, -- 设置排序类型, 非0 值则降序
18: @strWhere varchar(1500) = '' -- 查询条件(注意: 不要加where)
19: AS
20:
21: declare @strSQL varchar(5000) -- 主语句
22: declare @strTmp varchar(110) -- 临时变量
23: declare @strOrder varchar(400) -- 排序类型
24:
25: if @doCount != 0
26: begin
27: if @strWhere !=''
28: set @strSQL = 'select count(*) as Total from [' + @tblName + '] '+@innerJohn +' where '+@strWhere
29: else
30: set @strSQL = 'select count(*) as Total from [' + @tblName + '] '+@innerJohn +' '
31: end
32: --以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况
33:
34: else
35: begin
36: if @OrderType != 0
37: begin
38: set @strTmp = '<(select min'
39: set @strOrder = ' order by [' + @fldName +'] desc'
40: --如果@OrderType不是0,就执行降序,这句很重要!
41: end
42:
43: else
44: begin
45: set @strTmp = '>(select max'
46: set @strOrder = ' order by [' + @fldName +'] asc'
47: end
48: if @PageIndex = 1
49: begin
50: if @strWhere != ''
51: set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from [' + @tblName + '] '+@innerJohn +' where ' + @strWhere + ' ' + @strOrder
52: else
53: set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ['+ @tblName + '] '+@innerJohn + @strOrder
54: --如果是第一页就执行以上代码,这样会加快执行速度
55: end
56: else
57: begin
58: --以下代码赋予了@strSQL以真正执行的SQL代码
59: set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from '
60: + @tblName + ' '+@innerJohn+ ' where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['+ @fldName + '] from [' + @tblName + '] '+@innerJohn +' ' + @strOrder + ') as tblTmp)'+ @strOrder
61: if @strWhere != ''
62: set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from '
63: + @tblName + ' '+@innerJohn+ ' where [' + @fldName + ']' + @strTmp + '(['
64: + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
65: + @fldName + '] from [' + @tblName + '] '+@innerJohn +' where ' + @strWhere + ' '
66: + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
67: end
68: end
69:
70: print(@PageIndex)
71:
72: exec (@strSQL)
现在的页面效果图:
是不是蛮不错的????
可能有人会问,为什么要做这么多工作?
可是试想想,如果要把这些列表页生成静态页面,那么,这个页面就非常容易生成了,这个ajax分页更好更完美,
如果用服务器控件,只要存在VIEWSTATE,生成静态页面就没辙了.
而且这么设计结构清晰,更以维护,分离也更彻底!
一直在努力,从未曾放弃,努力学习中..... 欢迎一起学习.net!
摘自 TZHSWEET