ASP.NET MVC分页的实现(上)

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.configappsetting里的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再讨论。

你可能感兴趣的:(mvc,.net,分页,asp,休闲)