MVC学习之分页 【转】

分页
如果dinners列表记录过多,为了让用户更方便浏览,我们需要实现分页显示,而不是一次显示大量的记录列表。
Index() Action方法更新
DinnersController类的Index() action方法代码如下:
        //
        // GET: /Dinners/
        public ActionResult Index()
        {
            var dinners = dinnerRepository.FindUpcomingDinners().ToList();
            return View("Index", dinners);
        }
当用户请求/Dinners地址时,将返回所有即将来临的dinners列表,并在页面全部显示出来。
理解IQueryable<T>
IQueryable<T> 接口是.NET 3.5的LINQ中引入的,实现了强大的deferred execution,我们将利用这一特性实现分页功能。
在DinnerRepository类中,FindUpcommingDinners() 方法将返回IQueryable<Dinner>对象。
        public IQueryable<Dinner> FindUpcomingDinners()
        {
            return from dinner in db.Dinners
                   where dinner.EventDate > DateTime.Now
                   orderby dinner.EventDate
                   select dinner;
        }
FindUpcomingDinners() 方法返回的IQueryable<Dinner> 对象封装了使用LINQ to SQL从数据库中检索Dinner对象的查询。重要的是,该语句并不会对数据库执行查询,直到我们试图去访问或者遍历查询中的数据,或者我们调用ToList() 方法。调用FindUpcomingDinners() 方法在执行查询之前,可以选择添加额外的操作或过滤(chained operations/filters),当查询数据时,LINQ to SQL会聪明地对数据库执行组合查询。
为了执行分页逻辑,我们更新了Index() action 方法,在调用ToList() 方法之前,对返回的IQueryable<Dinner>序列应用了附加的Skip 和Take操作符。
//
// GET: /Dinners/
public ActionResult Index() {
var upcomingDinners = dinnerRepository.FindUpcomingDinners();
var paginatedDinners = upcomingDinners.Skip(10).Take(10).ToList();
return View(paginatedDinners);
}
上述代码跳过数据库中前10条即将来临的Dinners记录,接着返回10条记录。LINQ to SQL聪明地构造了优化的SQL查询,在SQL 数据库端实现上述逻辑,仅仅返回我们想要的10条记录,使查询性能更加优化和可扩展性。
在URL中添加page参数值
我们将在URL中包含page参数值,标识用户请求的分页,而不是在代码中硬编码特定的页面范围。
使用Querystring 参数值
下面的代码演示如何使用更新Index() action 方法,支持querystring 参数,URL地址如/Dinners?page=2。
// GET: /Dinners/
// /Dinners?page=2
public ActionResult Index(int? page) {
const int pageSize = 10;
var upcomingDinners = dinnerRepository.FindUpcomingDinners();
var paginatedDinners = upcomingDinners.Skip((page ?? 0) * pageSize)
.Take(pageSize)
.ToList();
return View(paginatedDinners);
}
上述Index() 方法有一个参数page,该参数定义为nullable 整型。/Dinners?page=2 地址表示2将传递为参数值。/Dinners 地址(没有querystring 参数)将传入一个空值。
我们通过page乘以页面记录数(page size,本范例为10)来决定需要跳过的dinners记录条数。同时,我们使用了C#操作符(??),该操作在处理nullable类型时,非常有用。如果page参数为空(null),上述代码将对page赋值为0。
使用嵌入的URL参数值
除了了querystring外,另外的一个办法是嵌入page参数到实际的URL中,如/Dinners/Page/2 或者/Dinners/2。ASP.NET MVC包含了一个强大的URL路由引擎,可以轻松支持上述场景。
我们可以注册定制的路由规则,映射任何进来的URL或URL格式到任何Controller控制器类和Action方法。可以通过打开项目中Global.asax文件来实现。
使用MapRoute() 辅助方法,注册一个新的映射规则,像第一次调用routes.MapRoute()方法:
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "UpcomingDinners",
                "Dinners/Page/{page}",
                new { controller = "Dinners", action = "Index" }
            );
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = ""// Parameter defaults
            );
        }
在上述代码中,我们注册了一个新的路由规则 – UpcommingDinners,URL格式为/Dinners/Page/{page},其中{page} 是嵌入在URL的参数。MapRoute() 方法将符合上述URL格式的请求映射到DinnersController类的Index() action 方法。
我们使用与Querystring方案中完全相同的Index() 方法,处理page参数将来自于URL,而不是querystring:
        //
        // GET: /Dinners/
        // /Dinners/Page/2
        public ActionResult Index(int? page)
        {
            const int pageSize = 10;
            var upcomingDinners = dinnerRepository.FindUpcomingDinners();
            var paginatedDinners = upcomingDinners.Skip((page ?? 0) * pageSize)
            .Take(pageSize)
            .ToList();
            return View(paginatedDinners);
        }
现在访问/Dinners URL时,将返回前10条记录,而不是全部记录了。
 
接下来访问/Dinners/Page/1 URL时,将看到下一页的Dinners记录。
 

添加页面导航界面
实现页面分页的最后一步是在视图模板中添加上一页、下一页的导航界面,方便用户在页面之间切换。
为了正确实现这一步,我们需要知道数据库中Dinners的记录数和需要分为多少页。接着,我们计算当前请求的页面是开始页或是最后页,并正确显示或隐藏上一页和下一页的导航链接。我们将在Index() action 方法中实现这一逻辑。另一选择是,我们在项目中添加一个辅助类,封装这一逻辑,实现更多地方的重用。
下面是一个简单PaginatedList 辅助类,继承.NET Framework 内置的List<T>集合类。它实现了一个可重用的集合类,用来在任何IQueryable序列中实现分页。在NerdDinner范例程序中,用来对IQueryable<Dinner> 结果集进行分页,但是它也可用于其他应用程序中对IQueryable<Product>或IQueryable<Customer>结果集进行分页。
    public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int PageSize { get; private set; }
        public int TotalCount { get; private set; }
        public int TotalPages { get; private set; }
        public PaginatedList(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));
        }
        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 0);
            }
        }
        public bool HasNextPage
        {
            get
            {
                return (PageIndex + 1 < TotalPages);
            }
        }
    }
上述类公开的4个属性,PageIndex、PageSize、TotalCount 和 TotalPages等等,另外公开了2个辅助属性:HasPreviousPage和HasNextPage,这2个属性分别表示是否页面数据在集合的开始页或者结束页。上述代码将引起执行2次SQL 查询,第一次检索Dinner Objects总记录数(不返回对象,仅仅是执行SELECT COUNT语句,返回一个整型值),第二次检索数据库,返回当前页需要的数据列表。
接着,我们更新DinnersController.Index() 辅助方法,从DinnerRepository.FindUpcomingDinners() 结果集中创建一个PaginatedList<Dinner> 对象,并传递给视图模板。
        // GET: /Dinners/
        // /Dinners/Page/2
        public ActionResult Index(int? page)
        {
            const int pageSize = 10;
            var upcomingDinners = dinnerRepository.FindUpcomingDinners();
            var paginatedDinners = new PaginatedList<Dinner>(upcomingDinners, page ?? 0, pageSize);
            return View(paginatedDinners);
        }
接着更新\Views\Dinners\Index.aspx 视图模板,从继承ViewPage<IEnumerable<Dinner>>更新为ViewPage<NerdDinner.Helpers.PaginatedList<Dinner>>,然后添加如下代码到视图模板的底部,显示或隐藏上一页和下一页的导航链接:
    <% if (Model.HasPreviousPage)
       { %>
    <%= Html.RouteLink("上一页","UpcomingDinners",new { page=(Model.PageIndex-1) }) %>
    <% } %>
    <% if (Model.HasNextPage)
       { %>
    <%= Html.RouteLink("下一页","UpcomingDinners",new { page = (Model.PageIndex + 1) })%>
    <% } %>
上述代码使用Html.RouteLink() 辅助方法生成HTML超链接,这一方法与我们前面使用的Html.ActionLink() 辅助方法比较相似。区别是生成URL地址时,使用Global.asax文件中设置的路由规则。确保生成的URL和Index() Action方法有相同的格式:/Dinners/Page/{page} – 其中{page} 参数值基于当前页的序号来提供。
 
现在,我们访问NerdDinner应用程序时,每次将展示10条Dinners记录。
 
在页脚也提供了上一页和下一页的导航链接,实现页面跳转。
来自西北的狼!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298855.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构件图

构件图 目录 构件图概要... 1 构件图中的事物及解释... 1 构件图中的关系及解释... 1 我的构件图... 1 构件图用于静态建模&#xff0c;是表示构件类型的组织以及各种构件之间依赖关系的图。构件图通过对构件间依赖关系的描述来估计对系统构件的修改给系统可能带来的影响…

不小心把硬盘摔了一下,结果电脑变成这样了......

1 会主动要求换尿裤的小宇航员▼2 其实赚钱这个事儿我也不太会▼3 春困、夏倦、秋乏、冬眠一年四季都好适合睡觉啊&#xff01;▼4 这是硬盘摔了&#xff0c;结果把显示器心疼坏了吧&#xff1f;▼5 柯基&#xff1a;弱小、可怜▼6 朋友相册里的你▼7 人类迷惑行为之放生…

win10前置耳机插孔没声音_音频服务未运行怎么办?win7和win10电脑没声音了恢复方法...

很多人可能都会问电脑没声音了&#xff0c;如何恢复&#xff1f;其实造成这种情况的原因有很多&#xff0c;一般需要一个一个排查。这次&#xff0c;小编跟大家分享其中的一个原因&#xff0c;以及具体的解决方法。个别小伙伴的笔记本电脑&#xff0c;每次开机总会提示音频服务…

开源 java CMS - FreeCMS2.2 系统配置

2019独角兽企业重金招聘Python工程师标准>>> 项目地址&#xff1a;http://www.freeteam.cn/ 系统配置 管理系统使用的配置项。 从左侧管理菜单点击系统配置进入。 从FreeCMS 1.7开始支持 数据变更后栏目页面静态化间隔时间(单位为分)&#xff1a;修改栏目、更新…

EF Core使用Simple Logging输出日志

在使用EF Core的时候&#xff0c;很多时候需要知道EF Core实际执行的SQL语句是什么。Simple Logging是EF Core提供的一项功能&#xff0c;可用于在开发和调试应用程序时轻松获取日志。这种形式的日志记录需要最少的配置&#xff0c;而不需要其他NuGet包。功能一瞥配置起来非常简…

如何用全球顶级名画,成为全行业最令人羡慕的人?

▲ 点击查看马克思曾说&#xff1a;“如果你想得到艺术的享受&#xff0c;那你就必须是一个有艺术修养的人。”假如现在有下面两幅画&#xff0c;站在艺术的角度上&#xff0c;你会选择哪个呢&#xff1f;或者我们可以换一个问法&#xff1a;哪一种猫才是最符合你心中标准的猫&…

电脑启动后黑屏只有鼠标_电脑加装固态硬盘后出现黑屏或蓝屏解决方案

以下内容以本人遇到的真实问题为例&#xff0c;从找到加装固态硬盘后出现黑屏及蓝屏的原因&#xff0c;到成功解决问题&#xff0c;请各位看官听我娓娓道来&#xff0c;也希望为遇到同样问题的广大网友拨云见日&#xff0c;废话不多说&#xff0c;走起……一、问题描述:1. 背景…

2021编程语言排行:C#飙升,Python蝉联榜首

文 | 白开水不加糖出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013&#xff09;IEEE Spectrum 2021 年度编程语言排行榜现已发布。该榜单一年发布一次&#xff0c;今年是其发布的第八年。今年的排行榜包含 55 种语言&#xff0c;其排序综合 8 个重要线上数据源的 11 …

GitHub中教程资源 | 共21个图形绘制教程

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 写在前面 今天分享在GitHub中找到的教程资源&#xff0c;此教程是来自iMeta期刊及“农心生信工作室”的作品。发表在GitHub中&#xff0c;大家可以自行下载。 包含了21个图形的绘制&#xff0c;我大体看了一下…

盘点那些欺骗我感情的数学定理

全世界只有3.14 % 的人关注了爆炸吧知识一直以来&#xff0c;关于定理、公式的命名&#xff0c;人们都倾向于用数学家的名字命名&#xff0c;不仅简单方便&#xff0c;还可以达到纪念创立人的效果。不过&#xff0c;也不是每一次都这么好的&#xff0c;超模君发现&#xff0c;有…

linux启动mysql_Linux服务器安装Mysql教程

最开始用服务器的时候&#xff0c;也是对这些环境的安装操作极其陌生&#xff0c;找了很多方式&#xff0c;写这边文章就是为了让更少的童鞋走弯路&#xff0c;下面我们看看具体的操作流程。1、首先关闭linux的防火墙&#xff0c;执行命令chkconfig iptables off2、从mysql官网…

黑人抬棺,虽迟但到

1 脑子里有声音了▼2 人活着可太难了▼3 受疫情影响&#xff0c;汤姆哈迪在家种菜了▼4 4岁小朋友的涂鸦对颜色搭配的天赋简直点满▼5 白天哈哈哈哈哈哈哈哈晚上呜呜呜呜呜呜呜呜▼6 反正是最后的晚餐了通融一下嘛▼7 喵娘报恩▼你点的每个赞&#xff0c;我都认真当成了…

本地搭建K8s环境,并配置Ingress代理(1)

书接上文&#xff0c;上回说到了在Linux系统搭建K8s环境&#xff0c;通过脚本一键处理&#xff0c;具体可参考《入门K8s&#xff1a;一键脚本搭建Linux服务器集群》。虽然Linux系统很不错&#xff0c;而且也推荐都买一个做练习&#xff0c;但是不可避免的会遇到一些小问题&…

简单链接Simplelink 传感器标签SensorTag

2019独角兽企业重金招聘Python工程师标准>>> 传感器标签现在支持iBeacon技术 为了让你的传感器标签升级到与iBeancon技术兼容&#xff0c;你需要和苹果公司签约一个iBeacon许可&#xff0c;然后你可以请求访问软件&#xff0c;通过点击这里http://www.ti.com/tool/s…

苹果手机透明桌面_原来苹果手机辨别真假很容易!查看桌面1个图标,就能轻松分辨...

要说哪个品牌的手机贵&#xff0c;大家想到的肯定是苹果手机啦&#xff0c;所以说很多朋友都害怕自己买到假货。其实分辨苹果手机是不是正品很容易&#xff0c;只需查看桌面1个图标&#xff0c;就能辨别出手机的真假哦。一、从细节入手1.桌面时钟不知道大家发现没&#xff0c;i…

Linux主机名那点事儿

Linux主机名那点事儿和windows一样&#xff0c;liunx同样有自己的主机名&#xff0c;主要用于识别机器和远成访问。事儿一、/etc/hosts文件主机和IP配置文件该文件其实就是告诉本机哪些域名对应那些ip&#xff0c;那些主机名对应哪些ip&#xff0c;因为ip地址难以记忆&#xff…

数学老师出的谜语,语文老师已哭晕在厕所!

全世界只有3.14 % 的人关注了爆炸吧知识数学老师出的这几个谜语&#xff0c;谜面都是数字和运算符号&#xff0c;谜底可都是四个字的成语。语文老师已经哭晕了&#xff0c;快来试试看&#xff0c;你能猜出几个&#xff1f;谜面&#xff1a;0000点击下方空白区域查看答案▼谜底&…

苹果手机怎么拍星空_手机拍星空,看这篇教程就够了!

直到现在还有很多人觉得&#xff0c;只有单反才能拍出璀璨的星空。事实上&#xff0c;手机也能拍出非常好看的星空作品&#xff0c;只要掌握这些要点就足够了。点击下方视频&#xff0c;学习手机拍星空觉得视频太快的同学&#xff0c;可以接着往下看详细教程图文版下面我们来学…

如何用数学方法估算一个女生前男友的数量?

全世界只有3.14 % 的人关注了爆炸吧知识如果一个女生说&#xff0c;她集齐了十二个星座的前男友&#xff0c;我们应该如何估计她前男友的数量&#xff1f;小学生&#xff1a;这个问题相当简单公式&#xff1a;数据&#xff1a;{白羊座, 金牛座, 双子座, 巨蟹座, 狮子座, 处女座…

Discuz!NT博客非官方升级!!

接触Discuz&#xff01;NT有很长的一段时间&#xff0c;从最初的神秘到现在的跃跃欲试&#xff0c;在这个九月最后一天&#xff0c;十一的前一天下午&#xff0c;终于完成了一次非官方升级&#xff01;哈哈这次做的工作主要在博客方面进行了扩展&#xff0c;原则上是&#xff0…