MVC3学习第十三章 佟掌柜第二弹——MVC3下利用陕北吴旗娃的分页控件实现数据分页...
本章学习内容
1.了解陕北吴旗娃的Mvc分页控件
2.利用分页控件实现MVC3下的商品分页
3.利用分页控件实现MVC3下一个页面多个分页以及ajax分页效果
1.了解陕北吴旗娃的Mvc分页控件
在webfrom里实现分页我们有太多强大的支持,比如微软自带的数据控件里有自带的分页,或者选用网上的很多分页控件,再不济就算在aspx页面里拼凑代码来分页也不是很难的,可是到了MVC里这些选择就变得少了,当然如果你愿意也可以在razor视图里拼凑分页代码,可是这不仅违背View的初衷,仅代码来看也是一件恶心的事,我们今天来介绍杨涛,网名Webdiyer、“陕北吴旗娃”的MVC分页控件,如果你在webform里用过他的分页控件的话,对他应该不是很陌生了,我们摘取他官网里里的简介来说明一下他的MVC分页控件,可以去官网查看详细http://www.webdiyer.com/
MvcPager主要功能有:
- 实现最基本的url route分页;
- 支持手工输入或选择页索引并对输入的页索引进行有效性验证;
- 支持使用ASP.NET MVC Ajax默认的MicrosoftAjax和MicrosoftMvcAjax客户端脚本库实现Ajax分页;
- 支持使用jQuery实现Ajax分页,生成的Html代码更精简;
- 支持Ajax分页模式下,若客户端浏览器不支持或禁用Javascript功能时安全降级为普通分页
- 搜索引擎友好,无论是普通分页还是Ajax分页,搜索引擎都可以直接搜索到所有页面。
- 支持ASP.NET MVC 1.0、2.0和3.0 版本;
- 支持IE、Firefox、Opera、Chrome及Safari等常用浏览器;
MvcPager分页控件仍在不断开发完善中,更多功能将在以后的升级版本中得到增强和完善,希望您在使用过程中提出您的宝贵意见和建议!
using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Web; using System.Web.Mvc; using MyShopTest.Models; using System.Data.Entity.Validation; using Webdiyer.WebControls.Mvc;namespace MyShopTest.Controllers {public class ProductController : Controller{private MyShopDataEntities db = new MyShopDataEntities();//列表public ViewResult Index(string title = ""){var products = Search(title);ViewBag.Name = title;return View(products.ToList());}//商品查询public IQueryable<Product> Search(string titles){var products = db.Products.Include(p => p.Category).Where(p => p.Id > 0);//此处的查询没有任何意义,只是返回所有数据products = products.OrderBy(p => p.AddTime);//根据时间升序排列//products = products.OrderByDescending(p => p.Id);//根据Id降序排列if (!string.IsNullOrEmpty(titles)){products = products.Where(p => p.Title.IndexOf(titles) > -1 || p.Category.Name.IndexOf(titles) > -1);}return products;}//商品浏览public ActionResult Browse(string title = "", int currentPage = 1){int pageSize = 3;//每页条数var products = Search(title).ToPagedList(currentPage, pageSize);ViewBag.Name = title;return View(products);}//商品展示public ViewResult Show(int cId = 0){var cat = db.Category.Single(c => c.Id == cId);//var cat = db.Category.Include(c => c.Products).Single(c => c.Id == cId);//两者作用一样,可以直接获取不用include,但是经测试发现没有给对应主外键的实体填写virtual修饰符时,不写Include得不到关联实体的值return View(cat);}//详细public ViewResult Details(int id){Product product = db.Products.Find(id);return View(product);}//添加public ActionResult Create(){ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name");return View();}//添加处理 [HttpPost]public ActionResult Create(Product product)//此时已经自动匹配好了 {try{//图片var file = Request.Files[0];var img = new CommonHelper().fileSaveAs(file, 0, 2);if (img.IndexOf("UpFile") > -1){product.ImgUrl = img;}else{ModelState.AddModelError("error", img);//添加了key的错误信息,前台使用Html.ValidationMessage(key)的形式访问,如果key为空,用Html.ValidationSummary(true)显示ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name", product.CategoryId);return View(product);}db.Products.Add(product);db.SaveChanges();return RedirectToAction("Index");}catch (DbEntityValidationException ex){string mes = ex.Message;ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name", product.CategoryId);return View(product);}}//编辑public ActionResult Edit(int id){Product product = db.Products.Find(id);ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name", product.CategoryId);return View(product);}//编辑处理 [HttpPost]public ActionResult Edit(int id, FormCollection collection){var product = db.Products.Find(id);//ModelState.IsValid,此处相当于后台验证,防止前台验证因为各种情况被跳过或失效try{bool updateRes = TryUpdateModel(product);//如果字段符合则会赋值,否则保持原有//db.Entry(product).State = EntityState.Modified;if (updateRes){//图片var file = Request.Files[0];var img = new CommonHelper().fileSaveAs(file, 0, 2);if (img.IndexOf("UpFile") > -1){product.ImgUrl = img;}//else//{// ModelState.AddModelError("", img);// ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name", product.CategoryId);// return View(product);//} db.SaveChanges();return RedirectToAction("Index");}else{ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name", product.CategoryId);ModelState.AddModelError("", "更新失败!");return View(product);}}catch (Exception){ViewBag.CategoryId = new SelectList(db.Category, "Id", "Name", product.CategoryId);return View(product);}}//删除处理 [HttpPost]public ActionResult Delete(FormCollection coll){string ids = coll["ckSelect"];foreach (var item in ids.Split(','))//循环每一项Id {if (item != "false")//筛选掉自动生成的checkbox初始值 {var user = db.Products.Find(Convert.ToInt32(item));db.Products.Remove(user);}}db.SaveChanges();return RedirectToAction("Index");}protected override void Dispose(bool disposing){db.Dispose();base.Dispose(disposing);}} }
修改Browse.cshtml完整源代码如下:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model PagedList<MyShopTest.Models.Product> @{ViewBag.Title = "商品浏览";Layout = "~/Views/Shared/MyMaster.cshtml"; } <h2>商品浏览</h2> @using (Html.BeginForm()) {<p>名称或类别:<input type="text" name="title" value="@ViewBag.Name" /> <input type="submit" value="查询" /></p> } <div ><table><tr><th>名称</th><th>价格</th><th>类别</th><th>上架时间</th><th>操作</th></tr>@foreach (var item in Model){<tr><td>@Html.CutString(item.Title, 10)</td><td>@Html.DisplayFor(modelItem => item.Price)</td><td>@Html.ActionLink(item.Category.Name, "Show", new { cId = item.CategoryId }) |</td><td>@Html.DisplayFor(modelItem => item.AddTime)</td><td>@Html.ActionLink("查看详细", "Details", new { id = item.Id }, new { target = "_blank" })|</td></tr>}</table>@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "currentPage" }) </div>
重新编译项目,运行先看一下效果,为了测试分页请先自行添加一些商品数据:
翻一下页:
翻页成功,我们来解析一下代码:
ProductController.cs
//商品查询public IQueryable<Product> Search(string titles){var products = db.Products.Include(p => p.Category).Where(p => p.Id > 0);//此处的查询没有任何意义,只是返回所有数据products = products.OrderBy(p => p.AddTime);//根据时间升序排列//products = products.OrderByDescending(p => p.Id);//根据Id降序排列if (!string.IsNullOrEmpty(titles)){products = products.Where(p => p.Title.IndexOf(titles) > -1 || p.Category.Name.IndexOf(titles) > -1);}return products;}//商品浏览public ActionResult Browse(string title = "", int currentPage = 1){int pageSize = 3;//每页条数var products = Search(title).ToPagedList(currentPage, pageSize);ViewBag.Name = title;return View(products);
Brwose方法我们加了一个参数是currenPage,表示当前页索引,这个参数是从视图里传过来的,默认加载第一页,我们把查询方法的返回值改为了IQueryable,是因为我们使用的分页控件有该接口的扩展方法ToPagedList,把我们查询出的结果进行分页处理,传入参数就是当前页和每页条数,然后把分页结果返回给视图。
Browse.cshtml:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model PagedList<MyShopTest.Models.Product>
引用命名控件,声明Model类型是PagedList<MyShopTest.Models.Product>,这个应该很好理解。
@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "currentPage" })
这里是实现分页的HtmlHelper方法,Pager方法它有很多重载形式,这里我们先选取了一种最简单的方式,后续会讲到复杂一些的形式,有兴趣的也可以自己研究一下。我们传入了当前分页数据的Model作为数据源,并且给分页参数指定了url页码参数名称是currentPage,这个名称可以自定义,默认是Id,要和你控制器里那个页码参数保持一致,
一个简答的分页到此基本就可以了,效果之前我们已经测试过了,为了看看分页功能是否健壮,我们再精细的测试一下,比如输入一个查询条件进行查询分页,看看结果是否正确。
点击下一页:
条件不见了,分页结果应该也是不正确的,说明我们的分页还不完善。除此之外我们还希望分页时可以显示总页数,每页条数,当前页码,假如数据多时最好还可以进行页码跳转等等,现在我们来改造我们的代码完成这些功能。
Browse.cshtml修改完整代码如下:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model PagedList<MyShopTest.Models.Product> @{ViewBag.Title = "商品浏览";Layout = "~/Views/Shared/MyMaster.cshtml"; } <h2>商品浏览</h2> <!--不指定form提交action,会默认提交到当前url(地址栏显示的action)--> @using (Html.BeginForm()) {<p>名称或类别:<input type="text" name="title" value="@ViewBag.Name" /> <input type="submit" value="查询" /></p> } <div><table><tr><th>名称</th><th>价格</th><th>类别</th><th>上架时间</th><th>操作</th></tr>@foreach (var item in Model){<tr><td>@Html.CutString(item.Title, 10)</td><td>@Html.DisplayFor(modelItem => item.Price)</td><td>@Html.ActionLink(item.Category.Name, "Show", new { cId = item.CategoryId }) |</td><td>@Html.DisplayFor(modelItem => item.AddTime)</td><td>@Html.ActionLink("查看详细", "Details", new { id = item.Id }, new { target = "_blank" })|</td></tr>}</table>@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "currentPage", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.DropDownList, ShowGoButton = false, PageIndexBoxWrapperFormatString = "跳转到{0}", FirstPageText = "首页" }, "default", new { title =ViewBag.Name })|共 @Model.TotalItemCount 条记录,页 @Model.CurrentPageIndex/@Model.TotalPageCount </div>
重新编译项目,运行:
输入查询条件,点击下一页查看:
没有问题,可以实现我们要的效果,至此一个稍微健全的分页到此就可以了。
3.利用分页控件实现MVC3下一个页面多个分页以及ajax分页效果
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Webdiyer.WebControls.Mvc;namespace MyShopTest.Models {public class MyDataList{public PagedList<Categeory> cList { get; set; }public PagedList<Product> pList { get; set; }} }
这个类里我们定义了两个属性,分别用来存储类别和商品的分页数据。
修改Product控制器的Browse的Action代码如下:
//商品浏览public ActionResult Browse(string title = "", int currentPage = 1, int currentPage2 = 1){int pageSize = 3;//每页条数var products = Search(title).ToPagedList(currentPage, pageSize);var categoryes = db.Category.OrderByDescending(c => c.Id).ToPagedList(currentPage2, pageSize);MyDataList list = new MyDataList();list.cList = categoryes;list.pList = products;ViewBag.Name = title;return View(list);}
修改Browse.cshtml完整代码如下:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model MyShopTest.Models.MyDataList @{ViewBag.Title = "商品浏览";Layout = "~/Views/Shared/MyMaster.cshtml"; } <h2>商品浏览</h2> <!--不指定form提交action,会默认提交到当前url(地址栏显示的action)--> @using (Html.BeginForm()) {<p>名称或类别:<input type="text" name="title" value="@ViewBag.Name" /> <input type="submit" value="查询" /></p> } <p>商品列表 </p> <div><table><tr><th>名称</th><th>价格</th><th>类别</th><th>上架时间</th><th>操作</th></tr>@foreach (var item in Model.pList){<tr><td>@Html.CutString(item.Title, 10)</td><td>@Html.DisplayFor(modelItem => item.Price)</td><td>@Html.ActionLink(item.Category.Name, "Show", new { cId = item.CategoryId }) |</td><td>@Html.DisplayFor(modelItem => item.AddTime)</td><td>@Html.ActionLink("查看详细", "Details", new { id = item.Id }, new { target = "_blank" })|</td></tr>}</table>@Html.Pager(Model.pList, new PagerOptions { PageIndexParameterName = "currentPage", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.DropDownList, ShowGoButton = false, PageIndexBoxWrapperFormatString = "跳转到{0}", FirstPageText = "首页" }, "default", new { title = ViewBag.Name })|共 @Model.pList.TotalItemCount 条记录,页 @Model.pList.CurrentPageIndex/@Model.pList.TotalPageCount </div> <p>类别列表: </p> <div><table><tr><th>类别名称</th><th>该类商品数</th></tr>@foreach (var item in Model.cList){<tr><td>@item.Name</td><td>@item.Products.Count</td></tr>}</table>@Html.Pager(Model.cList, new PagerOptions { PageIndexParameterName = "currentPage2", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.DropDownList, ShowGoButton = false, PageIndexBoxWrapperFormatString = "跳转到{0}", FirstPageText = "首页" }, "default", new { title = ViewBag.Name })|共 @Model.cList.TotalItemCount 条记录,页 @Model.cList.CurrentPageIndex/@Model.cList.TotalPageCount </div>
重新编译项目,运行,添加几条类别测试数据:
已经实现了我们一个页面多个分页的效果。
现在我们来修改我们的代码以实现ajax分页,提高用户体验:
在Views/Product上右键,添加分部视图,命名为ProBrowse,修改完整代码如下:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model PagedList<MyShopTest.Models.Product> <div id="divList1"><table><tr><th>名称</th><th>价格</th><th>类别</th><th>上架时间</th><th>操作</th></tr>@foreach (var item in Model){<tr><td>@Html.CutString(item.Title, 10)</td><td>@Html.DisplayFor(modelItem => item.Price)</td><td>@Html.ActionLink(item.Category.Name, "Show", new { cId = item.CategoryId }) |</td><td>@Html.DisplayFor(modelItem => item.AddTime)</td><td>@Html.ActionLink("查看详细", "Details", new { id = item.Id }, new { target = "_blank" })|</td></tr>}</table>@*@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "currentPage" })*@@Html.AjaxPager(Model, "", new { title = ViewBag.Name,type=1 }, new PagerOptions() { CssClass = "mvcPager", PageIndexParameterName = "currentPage", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.DropDownList, ShowGoButton = false, PageIndexBoxWrapperFormatString = "跳转到{0}", FirstPageText = "首页" }, new AjaxOptions() { UpdateTargetId = "divList1" }) </div>
在Views/Product上右键,添加分部视图,命名为CatBrowse,修改完整代码如下:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model PagedList<MyShopTest.Models.Categeory> <div id="divList2"><table><tr><th>类别名称</th><th>该类商品数</th></tr>@foreach (var item in Model){<tr><td>@item.Name</td><td>@item.Products.Count</td></tr>}</table>@Html.AjaxPager(Model, "default", new { title = ViewBag.Name, type = 2 }, new PagerOptions { PageIndexParameterName = "currentPage2", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.DropDownList, ShowGoButton = false, PageIndexBoxWrapperFormatString = "跳转到{0}", FirstPageText = "首页" }, new AjaxOptions() { UpdateTargetId = "divList2" })|共 @Model.TotalItemCount 条记录,页 @Model.CurrentPageIndex/@Model.TotalPageCount </div>
修改Browse.cshtml完整代码如下:
@using Webdiyer.WebControls.Mvc @using MyShopTest.Models @model MyShopTest.Models.MyDataList @{ViewBag.Title = "商品浏览";Layout = "~/Views/Shared/MyMaster.cshtml"; } <script src="../../Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script> <h2>商品浏览</h2> <!--不指定form提交action,会默认提交到当前url(地址栏显示的action)--> @using (Html.BeginForm()) {<p>名称或类别:<input type="text" name="title" value="@ViewBag.Name" /> <input type="submit" value="查询" /></p> } <p>商品列表 </p> @{Html.RenderPartial("ProBrowse",Model.pList);} <p>类别列表: </p> @{Html.RenderPartial("CatBrowse", Model.cList);}
在这些代码里,我们把商品和类别的分页类别哦分别在分部视图里实现了,在主页面(Browse)我们引用了jquery.unobtrusive-ajax.min.js,他在Scripts文件夹下,帮助我们实现ajax分页效果。我们单独把分页内容提出来是十分必要的
@Html.AjaxPager(Model, "default", new { title = ViewBag.Name, type = 2 }, new PagerOptions { PageIndexParameterName = "currentPage2", ShowPageIndexBox = true, PageIndexBoxType = PageIndexBoxType.DropDownList, ShowGoButton = false, PageIndexBoxWrapperFormatString = "跳转到{0}", FirstPageText = "首页" }, new AjaxOptions() { UpdateTargetId = "divList2" })
我们使用UpdateTargetId指定ajax分页得到的响应数据要替换的内容域,我们使用分部视图就可以保证在替换时只返回对应分部视图的内容而不是这个Browse的ActionResult避免出错,结合控制器代码大家应该很好理解,修改Product控制器Browse的Action代码如下:
//商品浏览public ActionResult Browse(string title = "", int currentPage = 1, int currentPage2 = 1, int type = 0){int pageSize = 3;//每页条数var products = Search(title).ToPagedList(currentPage, pageSize);var categoryes = db.Category.OrderByDescending(c => c.Id).ToPagedList(currentPage2, pageSize);MyDataList list = new MyDataList();list.cList = categoryes;list.pList = products;ViewBag.Name = title;if (Request.IsAjaxRequest() && type == 1){return PartialView("ProBrowse", products);}if (Request.IsAjaxRequest() && type == 2){return PartialView("CatBrowse", categoryes);}return View(list);}
没有复杂逻辑,我们在视图里将商品和类别分页请求分别加了type标识为1和2,当该Action收到ajax请求时,根据请求类型,返回对应分部视图,然后分页控件会替换指定内容域的内容为控制器返回的数据。
至此我们已经完成了分页功能
转载于:https://www.cnblogs.com/hswh/p/3171112.html
MVC3学习第十三章 佟掌柜第二弹——MVC3下利用陕北吴旗娃的分页控件实现数据分页...相关推荐
- 老李推荐:第14章8节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-获取控件列表并建立控件树 1...
老李推荐:第14章8节<MonkeyRunner源码剖析> HierarchyViewer实现原理-获取控件列表并建立控件树 poptest是国内唯一一家培养测试开发工程师的培训机构,以学 ...
- C#学习笔记(20140911)-下拉框、日历、pannel控件的使用
晚上学习了下拉框.日历.pannel控件的使用,这几个控件看上去好像没有之前的一些控件那么简单,但是使用起来还是很方便.使用完了后,才发现真的和之前的几种控件差不多. 最了一个小小的模块:每日签到填写 ...
- MVC3学习第六章 排山倒海第二变----使用 Entity Framework Code-First 进行数据访问
本章学习内容 1.Entity Framework 4.1介绍 2.Entity Framework Code-First 进行数据访问 3.利用EF实现用户的增加和列表功能 1.Entity Fra ...
- CCNA学习指南十三章
IPV6 IPV6地址类型: 单播地址:单播地址分为: 1.全球单播地址,是典型的.可路由的通用地址,像IPV4中的通用地址一样. 2.链路本地地址,就是IPV4中的专用(私有)地址,它们是不能路由的 ...
- C++PrimerPlus学习——第十三章编程练习
13-1 注意char*前面加const,不然就会报错 Classis.h #ifndef CLASSIC_H_ #define CLASS_H_ #include <string> cl ...
- .net学习之母版页执行顺序、jsonp跨域请求原理、IsPostBack原理、服务器端控件按钮Button点击时的过程、缓存、IHttpModule 过滤器...
1.WebForm使用母版页后执行的顺序是先执行子页面中的Page_Load,再执行母版页中的Page_Load,请求是先生成母版页的控件树,然后将子页面生成的控件树填充到母版页中,最后输出 2.We ...
- WPF学习:分页控件
好多年没有发博了,今天闲暇,把给公司做的ERP分页控件拿出来,有很多都用到分页的,所以就封装了一个UserControl分页控件,效果还不错,可以看看,先! 注意:有用到存储过程. 如果还不明白, ...
- javaFx学习之分页控件Pagination
原文链接:DOC-03-27 分页控件(Pagination Control) | JavaFX中文资料 JavaFX程序中添加分页(Pagination)控件.它会告诉你如何向程序中添加Pagina ...
- MFC学习--下拉框、列表、树控件、选项卡
下拉框.列表.树控件.选项卡 下拉框 属性 代码操作 列表控件 属性 代码操作 树控件 属性 代码操作 选项卡 属性 代码操作 文化建设 下拉框 属性 Data: 下拉可选项,用分号分隔( ; ) T ...
最新文章
- 这几道Redis面试题都不懂,怎么拿offer?
- CentOS firewall添加开放端口
- html 鼠标移动3d视图,HTML5 鼠标悬停3D平面摇晃动效
- pyspider 安装 和 快速开始
- 服务器日志文件中包含堆栈跟踪,日志框架 Logback 官方手册(第三章:Configuration)...
- 电脑Bois中usb模式启动热键
- 使用JasperReport 引擎PDF报表,因为iText版本升级,由原来的包名com.lowagie.text.pdf.fonts转化为com.itextpdf.text.pdf.fonts
- Vue.js(8)- 父组件给子组件传值
- 服务器2003系统无故重启,WINDOWS 2003 服务器自动定时重启的方法
- typedef用法详解
- 一步成高手:终极图解内存(上篇)
- 新一代最强开源UI自动化测试神器 Playwright - 元素定位
- mysql免安装版linux_Linux下配置免安装版的MySQL
- 面试算法———回溯经典题目
- BFC(Block Formatting Context) 及其如何工作
- python 2 入门
- python字符串的表示_python字符串的各种表达方式
- matlab BPSK调制方式代码实现
- Qwt使用之QwtPlot
- Crazy Learning for Day 7