在
ASP.NET
中,
GridView
控件本身就带有分页的功能,只要把当前页面的索引值赋给
GridView
的
PageIndex
就可以实现了分页,至于数据怎么分页,全都由
GridView
封装起来了。
在
ASP.NET MVC
中分页的实现就只能靠自己来设计了。首先来说一下分页的原理。现在有一个张
news
表,中间有很多信息,我们假设一页显示
5
条记录,这样,页面数量
=
总记录数
/5
;这里,如果出现小数,得进位取整。如比总记录和数为
51
,那么分的页面数量是
11
,最后一页只有一条记录。好,有这样一个思路后,现在就来做
ASP.NET MVC
中的分页了。
1、
数据库和表
创建一个
Data_Company
的数据库,建一张
news
表,表结构如下图:
ID
是主键,并助是自动增长列。
2、
现在,我们用
O/R Designer
来创建
news
表的
LINQ To SQL
的实体类。
创建一个名为
MvcCompany
的
ASP.NET MVC Web Application
项目,然后选中
Models
,右键,“添加”,“新建项”,选中
C#
中的“数据”,如下图:
选择“
LINQ to SQL
类”,名称设为“
CompanyData.dbml
”,然后“添加”。
打开“服务器资源管理器”,创建连接,展开表,找到
news
表,拖到
CompanyData.dbml
的左边表视图区(注:
.dbml
视图左边是
SQL
表和
SQL
视图区,右边是
SQL
存储过程和
SQL
函数区),效果如下图:
在“解决方案资源管理器”下的,“
Models
”多了三个文件,
CompanyData.dbml
,展开它,会有
CompanyData.dbml.layout
和
CompanyData.designer.cs
,前者是
CompanyData.dbml
视图的一些信息(比如
news
表在的坐标等信息),后者是
news
实体类及
Data_Company
数据库的类,在数据库类中聚合了
news
实体类。
3、
添加
news
列表类。因为一个
news
实体类,一次只能表示一条记录,如果呈现一个
news
表中的数据,最好定义一个集合类来存临时来存放
news
记录的集合。
类的实现如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
namespace
MvcCompany.Models
{
public class NewList<T> : List<T>
{
/// <summary>
///
页面索引值
/// </summary>
public int PageIndex { get; private set; }
/// <summary>
///
每页记录的数量
/// </summary>
public int PageSize { get; private set; }
/// <summary>
///
记录总条数
/// </summary>
public int TotalCount { get; private set; }
/// <summary>
///
共有的页数和
/// </summary>
public int TotalPages { get; private set; }
public NewList(IQueryable<T> source, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
//
进上去取整( 总记录条数/一面记录的条数)
TotalPages = (int)Math.Ceiling(TotalCount / (double)pageSize);
this.AddRange(source.Skip(pageIndex * pageSize).Take(PageSize));
}
/// <summary>
///
是否存在前续页
/// </summary>
public bool HasPreviousPage
{
get { return (PageIndex > 0); }
}
/// <summary>
///
是否存在后续页
/// </summary>
public bool HasNextPage
{
get { return (PageIndex + 1 < AllPages); }
}
}
}
这里,我们实现了一个泛型的集合列表
NewList
(当然,这里的本质上可以当其他实体类的集合列表),在这个类中间,有四个字段,访问修饰符都是
public
的,分另为:
PageIndex
:当前页面的索引值
PageSize
:每个页面的记录的条数
AllCount
:记录的总条数
AllPages
:共有的页面总数
在
NewList
构造函数中,有如下代码:
public
NewList(IQueryable<T> list, int pageIndex, int pageSize)
{
1
PageIndex = pageIndex;
2
PageSize = pageSize;
3
AllCount = source.Count();
4
AllPages = (int)Math.Ceiling(AllCount / (double)pageSize);
5
this
.AddRange(list.Skip(PageIndex * PageSize).Take(PageSize));
}
构造函的参数有三个,一个是
list
,就是实体类的一个集合,还有就是页面索引值和每个页面的记录条数。
第
1
、
2
代码很容易理角,第
3
行代码是得到列表的总记录条数,第
4
行代码,就完成了我们在开始时分析的分页实现的公式:页面数量
=
总记录数
/
每页记录数,其中
Math.Ceiling
就是把小数部分进到整数的函数。
最关键的是第
5
行代码,首先看
Skip(PageIndex*PageSize)
,页面索引值乘上每页记录数,得到是当前页面以前的所有记录数,
Skip
是跳过这些记录,而得到后面的所有记录,
Take(PageSize)
是得到
PageSize
条数的记录,比如,我们想要第三页的记录,这个页面的索引值为
2
(因为索引值从
0
开始)
PageIndex=2
,每页显示
5
条记录,
PageSize=5
,就是要跳过
list
中的前
10
条记录,然后再取前
5
条记录,即取
list
中的第
11
条到第
15
条记录,也就是第
3
页的记录了。
在这里,微软提供了
Skip
和
Tabke
函数,让我们做起分页来,得心应手。
接下来是
this.AddRange()
函数,可以把批量的数据放到当前集合中(因为
NewList
本身就是一个集合)。
代码的后半部分是两个属性:
public bool HasPreviousPage
{
get { return (PageIndex > 0); }
}
public bool HasNextPage
{
get { return (PageIndex + 1 < AllPages); }
}
这两个属性是为页面显示“上一页”和“下一页”,因为当我们显示第一页的时候,“上一页”是不需要显示的,如果最后一页,是没有“下一页“的,所以在这里定义了两个属性,来判断是否有上一页和下一页。
先看HasPreviousPage属性,如果PageIndex是大于0的,说明不是在第一页,所以就反回true,如果小于等于0(在这里小于0是没有意思义的,因为页面的索引值最小是0),说明是第一页,所以返回是false。
再看HasNextPage属性,因为页面索引值的最大数,与页面的最大数差1(索引从0开始的原因),所以当PageIndex+1小于AllPages时,说没有没到最后一页,返回值是true,如果PageIndex+1大于等于AllPages时(大于也没有意义),说明是最后一页,返回值为false。
4、
添加
NewsController
。选中
Controller
,右键添加一个
NewsController
的
Controller
。
代码如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
using
System.Web.Mvc.Ajax;
using
MvcCompany.Models;
using
System.Configuration;
namespace
MvcCompany.Controllers
{
public class NewsController : Controller
{
DataClassesDataContext DCDC;
int pageSize;
public NewsController()
{
DCDC = new DataClassesDataContext();
pageSize = Convert.ToInt32(ConfigurationManager.AppSettings["pagesize"]); //
每个页面的数量存放在web.config的appsetting里的pagesize节中,值为5
}
public ActionResult Index(int? page)
{
var NewsList = DCDC.news.Select(newss=>newss);
var paginatedNews = new NewList<news>(NewsList, page ?? 0, pageSize); //
实现分页功能
return View(paginatedNews);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection formValues)
{
int? index = int.Parse(formValues.GetValue("pageindex").AttemptedValue);
int page = index ??0 ;
var NewsList = DCDC.news.Select(newss => newss);
var paginatedNews = new NewList<news>(NewsList, page, pageSize); //
实现分页功能
return View(paginatedNews);
}
}
}
关于两个Index重载,我们在设计完Views再讨论。