• MVC 简单的分页思想与实现


      作为一个程序猿,数据分页是每个人都会遇到的问题。解决方案更是琳琅满目,花样百出。但基本的思想都是差不多的。

      下面给大家分享一个简单的分页器,让初学者了解一下最简单的分页思想,以及在ASP.NET MVC中的简单实现与应用。

    一,定义分页器类

      在ASP.NET MVC中,分页的数据源可能是各种不同的类型,所以最好使用泛型来定义。

    public class PagingHelper<T>

      

    二,基本三要素

      实现分页人所共知的三个基本属性:

    • DataSource:数据源,要知道数据源共计多少条数据,会对应一个数据源的方法-Count()
    • PageSize:来描述每页显示的记录的条数。
    • PageIndex:当前页的索引值,一般第一页的索引值为0,当然为了表示方便,可以从1开始,并且后面默认为从1开始。
    复制代码
    //分页数据源
    public IEnumerable<T> DataSource { get;private set; }
    //每页显示记录的数量
    public int PageSize { get; private set; }
    //当前页数
    public int PageIndex { get; set; }
    复制代码

      

    三,扩展属性

      有了上述三要素,我们可以推论其他三个重要属性

    • PageCount:总页数,其值取大于或等于 DataSource.Count/PageSize 的最小整数,比如5.2页,其实就是6页。
    • HasPrev:用来判断是否有上一页,如果索引 PageIndex 从1开始,那就是判断 PageIndex > 1 是否成立
    • HasNext:用力判断是否有下一页,如果索引 PageIndex 从1开始,需判断 PageIndex < PageCount 是否成立。
    复制代码
    //分页总页数
    public int PageCount { get;private set; }
    //是否有前一页
    public bool HasPrev { get { return PageIndex > 1; } }
    //是否有下一页
    public bool HasNext { get { return PageIndex < PageCount; } }
    复制代码

    四,核心方法

      最后就是需要实现分页的核心-获取分页数据的方法:

    • GetPagingData():获取当页的数据,一般常用的手段是跳过PageIndex*PageSize条记录,然后取PageSize条数据。

      在.NET中有很多方法可以实现这一过程,这里介绍2个最简单的:

      方法1,从序列的指定位置返回指定数量的连续元素:

    复制代码
     public static IEnumerable<TSource> Take<TSource>( this IList<TSource> list, int start, int count )
        {
          for ( int index = start; index < Math.Min( start + count, list.Count ); index++ )
          {
            yield return list[index];//yield关键字的用法大家可以参详其他文章
          }
        }
    复制代码

      那么我们的GetPagingData()方法就要这么写:

    //获取当前页数据
    public IEnumerable<T> GetPagingData()
    {
        return DataSource.ToList<T>().Take((PageIndex-1)×PageSize,PageSize);
    }

      

      其实我更倾向与第二种方法,就是使用IEnumerable<T>的扩展方法:

    • Skip(int count):跳过序列中指定数量的元素,然后返回剩余的元素
    • Take(int count):从序列的开头返回指定数量的连续元素。

      那么我们的GetPagingData()只需要这么写就完事:

    //获取当前页数据
    public IEnumerable<T> GetPagingData()
    {
        return DataSource.Skip((PageIndex - 1) * PageSize).Take(PageSize);
    }

      这句代码就是跳过 PageIndex - 1) * PageSize 条数据,再取 PageSize 条数据 ,刚刚好就是我们需要的当前页的数据。

     

    五,构造函数

      实例化一个分页器的时候,我们需要对它进行初始化:

    复制代码
      public PagingHelper(int pageSize, IEnumerable<T> dataSource)
            {
                this.PageSize = pageSize > 1 ? pageSize : 1;
                this.DataSource = dataSource;
                PageCount = (int)Math.Ceiling(dataSource.Count() / (double)pageSize);
            }
    复制代码

      真正的使用中,你可以重写分页器类,根据你的需要来控制哪些字段是只读的。比如你想随时改变页面元素的数量,那么你可以把PageSize设置为可读写的属性。

      至此,这个分页器我们就完工拉。


    六,与ASP.NET MVC的简单结合

      首先我们通过VS创建一个空的基于Razor视图引擎的ASP.NET MVC3 Web应用程序,命名为JohnConnor.Web

      对创建过程或Razor不太了解的看官,请移步 ASP.NET MVC Razor视图引擎攻略 <传送门> ,这里就不再赘述了。

      然后我们需要进行以下几步

      1,Models文件夹下,添加Student.cs文件,添加以下代码,为了演示方便这里模拟了一个数据源,实际中的数据源可能来自数据库。

    public class Student
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        public static class Students
        {
            public static IEnumerable<Student> data
            {
                get
                {
                    return new List<Student>()
                    {
                        new Student{ Id=0, Name="John"},
                        new Student{ Id=1, Name="Marry"},
                        new Student{ Id=2, Name="Andy"},
                        new Student{ Id=3, Name="Tom"},
                        new Student{ Id=4, Name="Lydia"},
                        new Student{ Id=5, Name="Chris"},
                        new Student{ Id=6, Name="Justin"},
                        new Student{ Id=7, Name="Susan"}
                    };
                }
            }
        }
    复制代码
        public class Student
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        public static class Students
        {
            public static IEnumerable<Student> data
            {
                get
                {
                    return new List<Student>()
                    {
                        new Student{ Id=0, Name="John"},
                        new Student{ Id=1, Name="Marry"},
                        new Student{ Id=2, Name="Andy"},
                        new Student{ Id=3, Name="Tom"},
                        new Student{ Id=4, Name="Lydia"},
                        new Student{ Id=5, Name="Chris"},
                        new Student{ Id=6, Name="Justin"},
                        new Student{ Id=7, Name="Susan"}
                    };
                }
            }
        }
    复制代码

      2,Models文件夹下,添加PagingHelper.cs文件,添加我们上述分页器类。

    public class PagingHelper<T>
        {
            //分页数据源
            public IEnumerable<T> DataSource { get; private set; }
            //每页显示记录的数量
            public int PageSize { get; private set; }
            //当前页数
            public int PageIndex { get; set; }
            //分页总页数
            public int PageCount { get; private set; }
    
            //是否有前一页
            public bool HasPrev { get { return PageIndex > 1; } }
            //是否有下一页
            public bool HasNext { get { return PageIndex < PageCount; } }
            //构造函数
            public PagingHelper(int pageSize, IEnumerable<T> dataSource)
            {
                this.PageSize = pageSize > 1 ? pageSize : 1;
                this.DataSource = dataSource;
                PageCount = (int)Math.Ceiling(dataSource.Count() / (double)pageSize);
            }
            //获取当前页数据
            public IEnumerable<T> GetPagingData()
            {
                return DataSource.Skip((PageIndex - 1) * PageSize).Take(PageSize);
            }
        }
    复制代码
     public class PagingHelper<T>
        {
            //分页数据源
            public IEnumerable<T> DataSource { get; private set; }
            //每页显示记录的数量
            public int PageSize { get; private set; }
            //当前页数
            public int PageIndex { get; set; }
            //分页总页数
            public int PageCount { get; private set; }
    
            //是否有前一页
            public bool HasPrev { get { return PageIndex > 1; } }
            //是否有下一页
            public bool HasNext { get { return PageIndex < PageCount; } }
            //构造函数
            public PagingHelper(int pageSize, IEnumerable<T> dataSource)
            {
                this.PageSize = pageSize > 1 ? pageSize : 1;
                this.DataSource = dataSource;
                PageCount = (int)Math.Ceiling(dataSource.Count() / (double)pageSize);
            }
            //获取当前页数据
            public IEnumerable<T> GetPagingData()
            {
                return DataSource.Skip((PageIndex - 1) * PageSize).Take(PageSize);
            }
        }
    复制代码

      3,在Controller文件夹下添加控制器命名为HomeController,添加以下代码。

    public class HomeController : Controller
        {
            public ActionResult Index(int pageIndex=1)
            {
                PagingHelper<Student> StudentPaging = new PagingHelper<Student>(2, Students.data);//初始化分页器
                StudentPaging.PageIndex = pageIndex;//指定当前页
                return View(StudentPaging);//返回分页器实例到视图
            }
        }
    复制代码
     public class HomeController : Controller
        {
            public ActionResult Index(int pageIndex=1)
            {
                PagingHelper<Student> StudentPaging = new PagingHelper<Student>(2, Students.data);//初始化分页器
                StudentPaging.PageIndex = pageIndex;//指定当前页
                return View(StudentPaging);//返回分页器实例到视图
            }
        }
    复制代码

      4,在View文件夹下添加Home文件夹,并新增视图文件Index.cshtml,添加以下代码。

    @using JohnConnor.Web.Models
    @model PagingHelper<Student>
    @{
        ViewBag.Title = "Index";
    }
    <h2>Index</h2>
    @foreach (var Data in Model.GetPagingData())
    {
        <p>ID:@Data.Id Name:@Data.Name</p>
    }
    <p>
    @if (Model.HasPrev)
    {
        <a href="@Url.Action("Index", "Home", new { pageIndex = Model.PageIndex - 1 })">上一页</a>
    }
    else
    {
        <em style="color:Gray">上一页</em>
    }
    @if (Model.HasNext)
    {
        <a href="@Url.Action("Index", "Home", new { pageIndex = Model.PageIndex + 1 })">下一页</a>
    }
    else
    {
          <em style="color:Gray">下一页</em>
    }
    </p>
    复制代码
    @using JohnConnor.Web.Models
    @model PagingHelper<Student>
    @{
        ViewBag.Title = "Index";
    }
    <h2>Index</h2>
    @foreach (var Data in Model.GetPagingData())
    {
        <p>ID:@Data.Id Name:@Data.Name</p>
    }
    <p>
    @if (Model.HasPrev)
    {
        <a href="@Url.Action("Index", "Home", new { pageIndex = Model.PageIndex - 1 })">上一页</a>
    }
    else
    {
        <em style="color:Gray">上一页</em>
    }
    @if (Model.HasNext)
    {
        <a href="@Url.Action("Index", "Home", new { pageIndex = Model.PageIndex + 1 })">下一页</a>
    }
    else
    {
          <em style="color:Gray">下一页</em>
    }
    </p>
    复制代码

      5,在Global.asax中配置路由,我们修改一下默认路由就可以了。

    public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    "Default", // 路由名称
                    "{controller}/{action}/{pageIndex}", // 带有参数的 URL
                    new { controller = "Home", action = "Index", pageIndex = UrlParameter.Optional } // 参数默认值
                );
    
            }
    复制代码
      public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    "Default", // 路由名称
                    "{controller}/{action}/{pageIndex}", // 带有参数的 URL
                    new { controller = "Home", action = "Index", pageIndex = UrlParameter.Optional } // 参数默认值
                );
    
            }
    复制代码

      现在保存之后F5运行,就可以看到一个简单的分页程序了。

      

       URL在进行了路由配置之后,也不会再是http://localhost:1234/Home/Index?pageIndex=1

      而变成了http://localhost:1234/Home/Index/1 这样的静态URL,更简洁,更美观。

      ---------------------------------------End---------------------------------------

      这篇中的提到分页器,只是一个很简易的分页思想的实现,其实本身的性能还是有待提高的。

      希望能抛砖引玉,哪位大神能分享出性能更强大的分页程序。

      文章中最后提到了URL重写与优化,如果看官们有兴趣,可以参见我之前的文章:

      ASP.NET MVC URL重写与优化(初级篇)-使用Global路由表定制URL

      ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL

      

      

     
    分类: ASP.NET MVC
    标签: ASP.NET MVC
  • 相关阅读:
    bootstrap之Click大事
    BZOJ 2878([Noi2012]-失落的游乐园树DP+出站年轮加+后市展望DP+vector的erase)
    cocos2d 消除类游戏简单的算法 (一)
    【BZOJ3627】【JLOI2014】路径规划 分层图
    Windows台cocos2d-x 3.2下载一个新的项目,创造的过程
    无插件,直接加参数,chrome它可以模拟手机浏览器
    unix您不能使用crontab设置运营计划
    LeetCode36:Valid Sudoku
    HDInsight HBase概观
    最受欢迎telnet
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2521290.html
Copyright © 2020-2023  润新知