不帅 发表于 2015-1-16 14:25:55

NET网页编程之详解ASP.NET MVC分页的完成办法

计算机发展到这个时候,很多技术日益成熟,想学好一种技术都是不容易的,当你学会用的时候你对它的很多原理可能很不了解)ASP.NETMVC分页已有良多文章报告过,这里我们将报告的ASP.NETMVC分页的完成,必要靠本人计划,这就必要懂得分页的道理,和相干数据库的操纵。在ASP.NET中,GridView控件自己就带有分页的功效,只需把以后页面的索引值赋给GridView的PageIndex就能够完成了分页,至于数据怎样分页,全都由GridView封装起来了。
ASP.NETMVC分页的完成就只能靠本人来计划了。起首来讲一下分页的道理。如今有一个张news表,两头有良多信息,我们假定一页显现5笔记录,如许,页面数目=总纪录数/5;这里,假如呈现小数,得进位取整。如比总纪录和数为51,那末分的页面数目是11,最初一页只要一笔记录。好,有如许一个思绪后,如今就来做ASP.NETMVC中的分页了。
1、数据库和表
创立一个Data_Company的数据库,建一张news表,表布局以下图:

ID是主键,并助是主动增加列。
2、如今,我们用O/RDesigner来创立news表的LINQToSQL的实体类。
创立一个名为MvcCompany的ASP.NETMVCWebApplication项目,然后选中Models,右键,“增加”,“新建项”,选中C#中的“数据”,以下图:

选择“LINQtoSQL类”,称号设为“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纪录的汇合。
类的完成以下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
namespaceMvcCompany.Models
{
publicclassNewList<T>:List<T>
{
/**////<summary>
///页面索引值
///</summary>
publicintPageIndex{get;privateset;}
/**////<summary>
///每页纪录的数目
///</summary>
publicintPageSize{get;privateset;}
/**////<summary>
///纪录总条数
///</summary>
publicintTotalCount{get;privateset;}
/**////<summary>
///共有的页数和
///</summary>
publicintTotalPages{get;privateset;}
publicNewList(IQueryable<T>source,intpageIndex,intpageSize)
{
PageIndex=pageIndex;
PageSize=pageSize;
TotalCount=source.Count();
//进上往取整(总纪录条数/一面纪录的条数)
TotalPages=(int)Math.Ceiling(TotalCount/(double)pageSize);
this.AddRange(source.Skip(pageIndex*pageSize).Take(PageSize));
}
/**////<summary>
///是不是存在前续页
///</summary>
publicboolHasPreviousPage
{
get{return(PageIndex>0);}
}
/**////<summary>
///是不是存在后续页
///</summary>
publicboolHasNextPage
{
get{return(PageIndex+1<AllPages);}
}
}}
这里,我们完成了一个泛型的汇合列表NewList(固然,这里的实质上能够当其他实体类的汇合列表),在这个类两头,有四个字段,会见润色符都是public的,分另为:
PageIndex:以后页面的索引值
PageSize:每一个页面的纪录的条数
AllCount:纪录的总条数
AllPages:共有的页面总数
在NewList机关函数中,有以下代码:
publicNewList(IQueryable<T>list,intpageIndex,intpageSize)
{
PageIndex=pageIndex;
PageSize=pageSize;
AllCount=source.Count();
AllPages=(int)Math.Ceiling(AllCount/(double)pageSize);
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自己就是一个汇合)。
代码的后半部分是两个属性:
publicboolHasPreviousPage
{
get{return(PageIndex>0);}
}
publicboolHasNextPage
{
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。
代码以下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Mvc;
usingSystem.Web.Mvc.Ajax;
usingMvcCompany.Models;
usingSystem.Configuration;
namespaceMvcCompany.Controllers
{
publicclassNewsController:Controller
{
DataClassesDataContextDCDC;
intpageSize;
publicNewsController()
{
DCDC=newDataClassesDataContext();
pageSize=Convert.ToInt32(ConfigurationManager.AppSettings["pagesize"]);//每一个页面的数目寄存在web.config的appsetting里的pagesize节中,值为5
}
publicActionResultIndex(int?page)
{
varNewsList=DCDC.news.Select(newss=>newss);
varpaginatedNews=newNewList<news>(NewsList,page??0,pageSize);//完成分页功效
returnView(paginatedNews);
}

publicActionResultIndex(FormCollectionformValues)
{
int?index=int.Parse(formValues.GetValue("pageindex").AttemptedValue);
intpage=index??0;
varNewsList=DCDC.news.Select(newss=>newss);
varpaginatedNews=newNewList<news>(NewsList,page,pageSize);//完成分页功效
returnView(paginatedNews);
}
}
}
关于两个Index重载,我们在计划完Views再会商。
5、增加View。选中NewsController,右键,增加View,会弹出以下图:

在这里,我们选中MvcCompany.Models.news,在Viewcontent下拉列表当选择List(由于要完成列表分页)。
Index.aspx页面代码以下:
<%@PageTitle=""Language="C#"MasterPageFile="http://www.lmwlove.com/ac/ID262/~/Views/Shared/Site.Master"Inherits="System.Web.Mvc.ViewPage<MvcCompany.Models.NewList<MvcCompany.Models.news>>"%>
<asp:ContentID="Content1"ContentPlaceHolderID="TitleContent"runat="server">
旧事
</asp:Content>
<asp:ContentID="Content2"ContentPlaceHolderID="MainContent"runat="server">
><!--前半部分-->
<%using(Html.BeginForm())
{%>
<h2>
旧事列表</h2>
<table>
<tr>
<th>
编号
</th>
<th>
标题
</th>
<th>
工夫
</th>
<th>
内容
</th>
</tr>
<%foreach(variteminModel)
{%>
<tr>
<td>
<%=Html.Encode(item.ID)%>
</td>
<td>
<%=Html.Encode(item.title)%>
</td>
<td>
<%=Html.Encode(String.Format("{0:g}",item.datetimes))%>
</td>
<td>
<%=Html.Encode(item.contents)%>
</td>
</tr>
<%}%>
</table>
<hr/>
><!--后半部分-->
<%=Html.RouteLink("首页","UpcomingNews",new{page=0})%>|
<%if(Model.HasPreviousPage)
{%>
<%=Html.RouteLink("上一页","UpcomingNews",new{page=(Model.PageIndex-1)})%>|
<%}%>
<%if(Model.HasNextPage)
{%>
<%=Html.RouteLink("下一页","UpcomingNews",new{page=(Model.PageIndex+1)})%>|
<%}%>
<%=Html.RouteLink("尾页","UpcomingNews",new{page=Model.PageSize-1})%>

<%=Html.TextBox("pageindex",Model.PageIndex,new{style="width:30px;"})%>页<input
type="submit"value="转到"id="sub"/>
<%}%>
</asp:Content>
代码的前半部分,很好了解。
代码的后半部分,我们来剖析一下,首页,是接纳Html.RouteLink(“首页”,”UpcomingNews”,new{page=0}),是要定位到称号为”UpcomingNews”的路由,这个路由在Global.asax中,代码以下:
routes.MapRoute(
"UpcomingNews",
"News/page/{page}",
new{controller="News",action="Index"});
路由的称号是”UpcominNews”,Url格局是News/page/{page},News和page是url的一种格局,前面{page}是参数,这个参数的称号要与View中,后半部分的new{page=0}的page,和NewsController中的办法Index(int?page)中的page都必须一致。假如有哀求
News/page/2的url,实践上哀求的是news?page=2的页网(路由在ASP.NETMVC官上有申明)。
首页为中的page=0,终极会成为NesController中Index(int?page)办法,的实参,前往首页数据(及数据库表的前5条数据)。
上一页,在以后页数PageIndex的基本上减1。
下一页,在以后页数PageIndex的基本上加1
(注:下面的加减1都不会越界,由于当显现第一页时,“上一页”的超毗连就不会显现。当最初一页时,“下一页”的超毗连就不会显现)
尾页同首页。
如今的一个成绩是“转到”第几页的完成,我们晓得,转到第几页的“几”,得用户输出,以是这里用一个Html.TextBox来完成,完整代码是
<%=Html.TextBox("pageindex",Model.PageIndex,new{style="width:30px;"})%>
终极会天生一个称号为pageindex的intup,范例为Text,它的值一直为以后的索引页值Model.PageIndex,个中有一个宽度的属性new{style="width:30px;"}。
同时另有一个<inputtype="submit"value="转到"id="sub"/>用来向后参提交。由于代码中有<form>表单,以是能够在NewsController中吸收这个提交。
Index(FormCollectionformValues)办法用来处置这个提交。这里会从formValues.GetValue("pageindex").AttemptedValue午时到客户端用户输出“pageindex”文本框中的值。从而来完成定向。
至此,我们就用ASP.NETMVC完成了一个分页功效,比拟之下要难ASP.NET的GridView主动分页很多多少。
在这个例子中,我们在Models层中供应了实体类及news表的汇合类。在Controller层增添了NewsController类。在View层增添了News的view,从M-V-C角度,分离完成了对分页的功效。
有时也搞不懂应该学那种;主要看你以后去的那个公司是使用哪种了。就像王千祥的课上说的:企业应用现在主要就三层(其实也差不多就是MVC):表示层(主要使用html写的,很简单)、业务逻辑层(主要就是应用服务器的)。最后就是数据层(其实就是学习数据库)

第二个灵魂 发表于 2015-1-18 14:27:56

通过这次激烈的讨论,我从大家身上学到了太多,开阔了眼界,不管是支持我的还是骂我的,都感谢你们。

爱飞 发表于 2015-1-24 16:50:45

有一丝可惜的是,这个系列太强了,Java阵营的朋友根本就是哑口无言...争论之火瞬间被浇灭,这不是我想这么早就看到的,但是值了。

山那边是海 发表于 2015-2-2 11:33:03

现在主流的网站开发语言无外乎asp、php、asp.net、jsp等。

愤怒的大鸟 发表于 2015-2-7 19:21:00

是指转换后的Servlet程序代码的行数。这给调试代码带来一定困难。所以,在排除错误时,可以采取分段排除的方法(在可能出错的代码前后输出一些字符串,用字符串是否被输出来确定代码段从哪里开始出错)。

蒙在股里 发表于 2015-2-23 09:34:15

由于CGI程序每响应一个客户就会打开一个新的进程,所以,当有多个用户同时进行CGI请求的时候,服务器就会打开多个进程,这样就加重了服务器的负担,使服务器的执行效率变得越来越低下。

柔情似水 发表于 2015-3-7 07:58:50

ASP.Net摆脱了以前ASP使用脚本语言来编程的缺点,理论上可以使用任何编程语言包括C++,VB,JS等等,当然,最合适的编程语言还是MS为.NetFrmaework专门推出的C(读csharp)。

金色的骷髅 发表于 2015-3-14 16:58:42

是指转换后的Servlet程序代码的行数。这给调试代码带来一定困难。所以,在排除错误时,可以采取分段排除的方法(在可能出错的代码前后输出一些字符串,用字符串是否被输出来确定代码段从哪里开始出错)。

飘飘悠悠 发表于 2015-3-21 13:32:51

ASP.Net摆脱了以前ASP使用脚本语言来编程的缺点,理论上可以使用任何编程语言包括C++,VB,JS等等,当然,最合适的编程语言还是MS为.NetFrmaework专门推出的C(读csharp)。
页: [1]
查看完整版本: NET网页编程之详解ASP.NET MVC分页的完成办法