三个分页组件
分页功能在项目中比较常见,一般的查询数据列表展示时都要求分页,它可以有效加快网页的响应速度,不是全部查询展示出来而是展示一页的数据。大部分的js组件也自带分页功能比如:ligerUI,只要把查询出来的数据转换成需要的数据格式(xml或json)丢给它就可以自动分页。winform自带的DataGridView组件也有该功能。
实现思路:需要三个变量,PageSize 每页的条数,PageCount 总页数,RecordCount总的记录数,PageIndex当前页 还有必要的查询参数,比如关键字、排序字段、特殊条件等。就可以生成一系列的页码,通过get或post请求到后台经过处理,把页面的数据取出来绑定到前台或客户端就可以了。
分享三个具有基础功能的分页插件,在我们的项目中用的也比较多,我把代码贴出来,又分别作了三个简单的demo,文章后面可以down下来,没有太多需要解释的代码,看命名应该就可以理解。
一、MvcPager分页组件
MvcPager是一个成熟开源的分页组件,支持路由分页、jquery ajax分页、支持在mvc4和mvc5应用程序中分页、兼容当前主流的浏览器, 主要在asp.net mvc中应用的比较多, 这是作者的博客http://www.webdiyer.com/mvcpager/ ,关于它的功能说明、应用、使用博客介绍的比较详细。下面是一个简单的路由分页demo。
用法:
(1)首先引入MvcPager.dll文件;
(2)前台
@model
PagedList
<
Article
>
@
using
TestPicture.Models
@
using
Webdiyer.WebControls.Mvc;
<
table
width
="100%">
<
tr
>
<
th
>
标题
</
th
>
<
th
>
日期
</
th
>
<
th
>
作者
</
th
>
<
th
>
来源
</
th
>
</
tr
>
@
foreach
(
var
item
in
Model)
{
<
tr
>
<
td
>
@Html.DisplayFor(modelItem => item.Title)
</
td
>
<
td
>
@Html.DisplayFor(modelItem => item.PubDate)
</
td
>
<
td
>
@Html.DisplayFor(modelItem => item.Author)
</
td
>
<
td
>
@Html.DisplayFor(modelItem => item.Source)
</
td
>
</
tr
>
}
</
table
>
@Html.Pager(Model,
new
PagerOptions
{
PageIndexParameterName =
"id"
,
ShowPageIndexBox =
true
,
FirstPageText =
"首页"
,
PrevPageText =
"上一页"
,
NextPageText =
"下一页"
,
LastPageText =
"末页"
,
PageIndexBoxType =
PageIndexBoxType
.TextBox,
PageIndexBoxWrapperFormatString =
"请输入页数{0}"
,
GoButtonText =
"转到"
})
(3)后台
///id是当前页
public
ActionResult
TestMvcPager(
int
id = 1)
{
int pageSize=2;//默认给定每页显示2条
var
model = articleList.AsQueryable().ToPagedList(id,
pageSize
);//
articleList是测试数据
return
View(model);
}
二、PagerHelper的一个通用的分页组件
这是一个生成分页页码的通用类,支持传递各种查询参数按照条件生成html页码,在我们开发的项目中用的比较多。
public
class
PagerHelper
{
///
<summary>
///
生成分页代码
///
</summary>
///
<param name="pageURL">
分页链接URL,页码用{0}进行占位
</param>
///
<param name="pageIndex">
当前页
</param>
///
<param name="pageCount">
总页数
</param>
///
<param name="recordCount">
总记录数
</param>
///
<returns>
分页HTMl代码
</returns>
public
static
string
Pager(
string
pageURL,
int
pageIndex,
int
pageCount,
int
recordCount = 0)
{
StringBuilder
builder =
new
StringBuilder
();
int
iStart = pageIndex - 5;
int
iEnd = iStart + 11;
if
(iStart < 1) { iStart = 1; }
if
(iEnd > pageCount) { iEnd = pageCount; }
if
(recordCount == 0)
{
builder.AppendFormat(
" <span style='padding:4px 0; display:inline-block;'>记录数 0 第0页/共0页 </span>"
);
}
else
{
builder.AppendFormat(
" <span style='padding:4px 0; display:inline-block;'>记录数 {2} 第{0}页/共{1}页 </span>"
, pageIndex, pageCount, recordCount);
}
if
(pageIndex > 1)
{
builder.Append(MakePageLink(
string
.Format(pageURL, pageIndex - 1),
"上一页"
,
false
));
}
for
(
int
i = iStart; i <= iEnd; i++)
{
builder.Append(MakePageLink(
string
.Format(pageURL, i), i.ToString(), (i == pageIndex)));
}
if
(pageIndex < pageCount)
{
builder.Append(MakePageLink(
string
.Format(pageURL, pageIndex + 1),
"下一页"
,
false
));
}
return
builder.ToString();
}
//生成分页链接
static
string
MakePageLink(
string
pageURL,
string
pageText,
bool
isCurrentPage)
{
string
strPageLink =
string
.Empty;
if
(isCurrentPage)
{
//当前页
strPageLink =
string
.Format(
"<span class='fcs'>{1}</span>"
, pageURL, pageText);//
样式可做修改
}
else
{
strPageLink =
string
.Format(
"<a href='{0}'
style='color:blue;text-align:center;'
>{1}</a>"
, pageURL, pageText);//样式可做修改
}
return
strPageLink;
}
///
<summary>
///
获取总页数
///
</summary>
///
<param name="recordCount">
记录总数
</param>
///
<param name="pageSize">
每页条数
</param>
///
<returns></returns>
public
static
int
GetPageCount(
int
recordCount,
int
pageSize)
{
if
(pageSize <= 0 || recordCount <= 0)
return
0;
int
num = recordCount / pageSize;
if
(recordCount % pageSize != 0)
{
num = num + 1;
}
return
num;
}
}
用法:
前台页面:
string
strBaseUrl = Url.Content(
"~/Home/TestPagerHelper"
);//请求的地址
int
pageIndex = ViewBag.PageIndex;
int
pageCount = ViewBag.PageCount;
int
recordCount = ViewBag.RecordCount;
string
strPageURL =
string
.Format(
"{0}/{1}/?q={2}"
, strBaseUrl,
"{0}"
, Server.UrlEncode(ViewBag.Keyword));//这个地址可以传递查询参数。
"{0}"
显示页码的占位符。
@Html.Raw(TestPageHelper.Models.
PagerHelper
.Pager(strPageURL, pageIndex, pageCount, recordCount))
后台:
///id是当前页
public
ActionResult
TestPagerHelper(
int
id = 1)
{
int
pageIndex = id;
string
keyWord = Request.QueryString[
"q"
];//关键字,也可以传递其他参数参数
int
pageSize = 2;//默认每页条数
int
recordCount = ArticleList.Count;//
ArticleList测试数据
if
(pageIndex <= 1) pageIndex = 1;
ViewBag.PageIndex = pageIndex;
ViewBag.RecordCount = recordCount;
ViewBag.PageCount = TestPageHelper.Models.
PagerHelper
.GetPageCount(recordCount, pageSize);
var
data = articleList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList<
Article
>();
return
View(data);
}
三、winform分页组件
这个比较简单,自定义一个用户控件,拖拉一大堆控件,在用户控件里面实现几个事件,网上也有很多实现,我私下也写了一个,不过对比
http://www.cnblogs.com/cyq1162/archive/2012/06/12/2545764.html,作者的简洁了不少。如下:
1、自定义一个用户控件;
2、实现上面的功能
代码如下:
#region
默认设置,每页大小可以修改pageSize的值,专门供外部调用
///
<summary>
///
设置默认情况,供外部调用
///
</summary>
///
<param name="recordNum">
总记录数
</param>
public
void
DrawControl(
int
recordNum)
{
RecordCount = recordNum;
DrawControl(
false
);//false表示不调用分页事件
}
#endregion
#region
分页字段和属性
private
int
pageIndex = 1;
///
<summary>
///
当前页
///
</summary>
public
virtual
int
PageIndex
{
get
{
return
pageIndex; }
set
{ pageIndex =
value
; }
}
///
<summary>
///
默认是10条,可根据需要修改,重新生成,未修改值注意查看.resx文件
///
</summary>
private
int
pageSize = 10;
///
<summary>
///
每页的大小
///
</summary>
public
virtual
int
PageSize
{
get
{
return
pageSize; }
set
{ pageSize =
value
; }
}
private
int
recordCount = 0;
///
<summary>
///
总记录数
///
</summary>
public
virtual
int
RecordCount
{
get
{
return
recordCount; }
set
{ recordCount =
value
; }
}
private
int
pageCount = 0;
///
<summary>
///
总页数
///
</summary>
public
virtual
int
PageCount
{
get
{
if
(PageSize != 0)
{
pageCount = GetPageCount();
}
return
pageCount;
}
}
///
<summary>
///
计算总页数
///
</summary>
///
<returns></returns>
private
int
GetPageCount()
{
if
(PageSize == 0)
{
return
0;
}
int
pageCount = RecordCount / PageSize;
if
(RecordCount % PageSize != 0)
{
pageCount = RecordCount / PageSize + 1;
}
return
pageCount;
}
#endregion
#region
事件处理
///
<summary>
///
引发分页时绑定该事件
///
</summary>
public
event
EventHandler
OnPageChanged;
///
<summary>
///
首页
///
</summary>
private
void
lnkFirst_LinkClicked(
object
sender,
LinkLabelLinkClickedEventArgs
e)
{
PageIndex = 1;
DrawControl(
true
);
}
///
<summary>
///
尾页
///
</summary>
private
void
lnkLast_LinkClicked(
object
sender,
LinkLabelLinkClickedEventArgs
e)
{
PageIndex = PageCount;
DrawControl(
true
);
}
///
<summary>
///
上一页
///
</summary>
private
void
lnkPrev_LinkClicked(
object
sender,
LinkLabelLinkClickedEventArgs
e)
{
PageIndex =
Math
.Max(1, PageIndex - 1);
DrawControl(
true
);
}
///
<summary>
///
下一页
///
</summary>
private
void
lnkNext_LinkClicked(
object
sender,
LinkLabelLinkClickedEventArgs
e)
{
PageIndex =
Math
.Min(PageCount, PageIndex + 1);
DrawControl(
true
);
}
///
<summary>
///
重绘按钮可用
///
</summary>
///
<param name="callEvent">
true标识调用事件处理
</param>
private
void
DrawControl(
bool
callEvent)
{
lblCurrentPage.Text = PageIndex.ToString();
lblPageCount.Text = PageCount.ToString();
lblTotalCount.Text = RecordCount.ToString();
txtPageSize.Text = PageSize.ToString();
if
(callEvent && OnPageChanged !=
null
)
{
OnPageChanged(
this
,
null
);
//当前分页数字改变时,触发委托事件
}
SetFormCtrEnabled();
if
(PageCount == 1)
//有且仅有一页
{
lnkFirst.Enabled =
false
;
lnkPrev.Enabled =
false
;
lnkNext.Enabled =
false
;
lnkLast.Enabled =
false
;
btnGo.Enabled =
false
;
}
else
if
(PageIndex == 1)
//第一页
{
lnkFirst.Enabled =
false
;
lnkPrev.Enabled =
false
;
}
else
if
(PageIndex == PageCount)
//最后一页
{
lnkNext.Enabled =
false
;
lnkLast.Enabled =
false
;
}
}
///
<summary>
///
设置窗体按钮可用
///
</summary>
private
void
SetFormCtrEnabled()
{
lnkFirst.Enabled =
true
;
lnkPrev.Enabled =
true
;
lnkNext.Enabled =
true
;
lnkLast.Enabled =
true
;
btnGo.Enabled =
true
;
}
///
<summary>
///
跳转页码enter键处理
///
</summary>
private
void
txtPageNum_KeyPress(
object
sender,
KeyPressEventArgs
e)
{
if
(e.KeyChar == (
char
)13)
{
btnGo_Click(
null
,
null
);
}
}
///
<summary>
///
跳转
///
</summary>
private
void
btnGo_Click(
object
sender,
EventArgs
e)
{
int
num = 0;
if
(
int
.TryParse(txtPageNum.Text.Trim(),
out
num) && num > 0)
{
PageIndex = num;
DrawControl(
true
);
}
}
///
<summary>
///
验证输入值有效且在总页数内
///
</summary>
private
void
txtPageNum_TextChanged(
object
sender,
EventArgs
e)
{
int
num = 0;
if
(
int
.TryParse(txtPageNum.Text.Trim(),
out
num) && num > 0)
{
if
(num > PageCount)
{
txtPageNum.Text = PageCount.ToString();
}
}
}
bool
isPageSizeTxtChanged =
false
;
///
<summary>
///
每页大小改变时
///
</summary>
private
void
txtPageSize_TextChanged(
object
sender,
EventArgs
e)
{
int
num = 0;
if
(
int
.TryParse(txtPageSize.Text.Trim(),
out
num) && num > 0)
{
isPageSizeTxtChanged =
true
;
PageSize = num;
}
}
///
<summary>
///
每页大小设置后后鼠标离开加载第一页的处理
///
</summary>
private
void
txtPageSize_MouseLeave(
object
sender,
EventArgs
e)
{
if
(isPageSizeTxtChanged)
{
lnkFirst_LinkClicked(
null
,
null
);
}
}
#endregion
3、用法
(1)注册一个事件:OnPageChanged;
(2)修改默认值,PageSize每页大小,调用DrawControl()方法初始化组件;
(3)代码如下:
List
<
Article
> list =
null
;
private
void
Form1_Load(
object
sender,
EventArgs
e)
{
pageControl1.OnPageChanged +=
new
EventHandler
(pageControl1_OnPageChanged);
LoadData();
}
void
pageControl1_OnPageChanged(
object
sender,
EventArgs
e)
{
LoadData();
}
void
LoadData()
{
if
(list ==
null
) list = GetTestData();//获取测试数据
pageControl1.DrawControl(list.Count);
var
data = list.Skip((pageControl1.PageIndex - 1) * pageControl1.PageSize).Take(pageControl1.PageSize)
.ToList<
Article
>();
dataGridView1.DataSource = data;
}
Demo下载:
MvcPager Demo
PagerHelper Demo
winform分页组件 Demo
PS: 软件工程涉及到软件开发过程中的方方面面,需求调研、需求分析、需求细化、需求变更,
项目计划、立项,
数据库概要设计、详细设计,架构、接口、
组件
设计,编码实现,静态资源管理(js、css、附件), 测试管理,中间要产生很多文档,配置管理,变更文档,风险控制,部署升级,维护,上线 ,运维等过程。有很多变化的东西(主要指需求),也有很多不变化的东西(SDK),经过项目实践这些尽可能的剥离业务,通用的类库、组件被积累下来,ORM DAL层,通用的数据处理框架层(主要是取数据、缓存、IO、文件操作、流处理、日志、验证、反射、异常、配置读写、字符处理、IOC、工厂等),杂七杂八的Common层(主要是:分页、导出、文件转换、共用处理、简单工具等)。这些类库、SDK、组件、js插件库等第三方开源的程序集像是一部机器中的各种不同的零件,开发的结果就是快速组装这样一部机器的过程。为你灵活的处理业务提高了效率。所以对技术框架和各种组件的熟悉、使用(解决什么问题)、原理、设计的学习是很有必要的。