环境:
win10
参考:
学习ASP.NET MVC(十一)------分页 - DotNet菜园 - 博客园
https://www.cnblogs.com/chillsrc/p/6554697.html
ASP.NET MVC+EF框架实现分页_ef 异步分页-CSDN博客
https://blog.csdn.net/qq_40052237/article/details/106599528
本文略去CRUD代码,默认读者可以连接数据库实现增删改查。之前写过:
ASP.NETMVC-简单例子-数据库查询+razor使用+项目发布_mvc怎么数据库搜索-CSDN博客
https://blog.csdn.net/pxy7896/article/details/139837179
目录
效果
准备工作
- 使用NuGet安装PagedList.Mvc,安装完成后PagedList也会被安装好。
- 可选:使用
BeginForm
时需要异步提交,所以使用jquery.unobtrusive-ajax.min.js。
html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ajax-unobtrusive/3.2.6/jquery.unobtrusive-ajax.min.js"></script>
可以下载放到Scripts文件夹下,使用BundleConfig引入。
思路
跟上一篇文章类似,区别是ViewModel里使用IPagedList<>
,连带着前端和后端都有变化。下面直接放代码了。
上一篇:
ASP.NET MVC-制作获取数据并分页的组件-原生代码版-CSDN博客
https://blog.csdn.net/pxy7896/article/details/140372682
实现
ViewModel
csharp
public class ViewMyObject
{
public IPagedList<MyObject> MyObject { get; set; }
public string Search { get; set; } // 关键词
public string Stype { get; set; } // sur-type
public string SortBy { get; set; } // asc or desc
public string PageSize { get; set; } // 每页多少个对象
public int TotalRows { get; set; } // 总共有多少条数据
}
前端
需要注意的有两点:
- Ajax.BeginForm可以发送异步请求,直接更新UpdateTargetId的内容,这个直接更新整个cshtml就可以了;
- BeginForm下,@Html.XX中形成的元素id与name一致,并且是可以跟指定的Action中的形参一致的:
- @Html.PagedListPager可以非常灵活地使用,通过设置
AjaxOptions
可以异步地更新数据。
给这个片段起名SearchIndex,内容如下:
html
@model xxx.ViewMyObject
@using PagedList.Mvc
@{
ViewBag.Title = "查询";
}
<div id="resultDiv">
@using (Ajax.BeginForm("SearchIndex", "Home", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "resultDiv" }))
{
<p>
种类: @Html.DropDownList("Category", "All")
名称: @Html.TextBox("searchString")
排序: @Html.DropDownList("sortBy", "不排序")
每页显示
@Html.DropDownList("pageSize", "10")
条数据
<input type="submit" value="查询" />
</p>
}
@if (Model != null)
{
<table>
<!-- 与上一篇完全一致,略 -->
</table>
<!-- 翻页 -->
<div>
共 @Model.TotalRows 条数据,第@(Model.MyObject.PageCount < Model.MyObject.PageNumber ? 0 : Model.MyObject.PageNumber)页,共 @Model.MyObject.PageCount 页
@Html.PagedListPager(Model.MyObject,
page => Url.Action("SearchIndex", new {
category = Model.Stype,
search = Model.Search,
sortBy = Model.SortBy,
page,
pageSize = Model.PageSize
}),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(
new PagedListRenderOptions {
Display = PagedListDisplayMode.IfNeeded,
DisplayLinkToFirstPage = PagedListDisplayMode.Never,
DisplayLinkToLastPage = PagedListDisplayMode.Never,
DisplayLinkToIndividualPages = true,
MaximumPageNumbersToDisplay = 5,
DisplayLinkToPreviousPage = PagedListDisplayMode.Always,
DisplayLinkToNextPage = PagedListDisplayMode.Always
},
new AjaxOptions {
HttpMethod = "GET",
UpdateTargetId = "resultDiv",
InsertionMode = InsertionMode.Replace
}
)
)
</div>
}
</div>
主页面
与上一篇一致:
html
@Html.Partial("SearchIndex", Model.ViewMyObject)
主页面控制器
首先,必须要在主页面带的对象的类定义里增加ViewMyObject类的变量,并且在初始化主页面的对象时,也初始化这个ViewMyObject类的变量。
其次,数据更新的代码如下所示,需要注意的点有:
- 通过ViewBag传递的变量,在初始化主页面的对象时也要初始化;
- 如果要带搜索功能的话,一定要先完成搜索/筛选,最后写分页。如果提前写了分页,那搜索功能会只局限在当前页面;
- 初始化ViewMyObject时,对于
IPagedList<>
类型的变量,不能直接使用来自类似这样的语句的变量var myObject = from m in db.myObject select m;
,而要经过一个OrderBy
操作,不然会报错:
shell
The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
只要取消蓝圈部分的注释就不会报错了。
更新表格数据的代码如下:
csharp
public ActionResult SearchIndex(string Category, string searchString, string sortBy, int? page, string pageSize)
{
MyDbContext db = new MyDbContext();
// 构造类型选择框
var cateLst = new List<string>();
var cateQry = from d in db.myObject
orderby d.stype
select d.stype;
cateLst.AddRange(cateQry.Distinct());
ViewBag.Category = new SelectList(cateLst);
//排序选项
var orderbyLst = new Dictionary<string, string>
{
{ "名称升序", "name_asc" },
{ "名称降序", "name_desc" }
};
ViewBag.sortBy = new SelectList(orderbyLst, "Value", "Key");
// 每页放多少数据的选项
ViewBag.pageSize = new SelectList(new List<string>() { "20", "50", "100"});
// 获取原始数据
var myObject = from m in db.myObject
select m;
// searchString匹配name
if (!String.IsNullOrEmpty(searchString))
{
myObject = myObject.Where(b => b.name.Contains(searchString));
}
// sort by name order
switch (sortBy)
{
case "name_asc":
myObject = myObject.OrderBy(b => b.name);
break;
case "name_desc":
myObject = myObject.OrderByDescending(b => b.name);
break;
default:
myObject = myObject.OrderBy(b => b.id);
break;
}
// sort by type
if (!string.IsNullOrEmpty(Category)) {
//string tmpType = Category.Replace("'", "''");
myObject = myObject.Where(x => x.stype == Category);
}
//分页
int pageItems = 10;// 每页放几个
if (!string.IsNullOrEmpty(pageSize)) {
pageItems = int.Parse(pageSize);
}
// view model
ViewMyObject vbp = new ViewMyObject();
int currentPage = (page ?? 1);
IPagedList<MyObject> pageMyObject = myObject.ToPagedList(currentPage, pageItems);
vbp.MyObject = pageMyObject;
vbp.Stype = Category;
vbp.SortBy = sortBy;
vbp.Search = searchString;
vbp.PageSize = pageSize;
vbp.TotalRows = myObject.Count();
return PartialView("SearchIndex", vbp);
}
彩蛋
如果要在单独的网页上更新,不需要做成组件,就比较简单了。此时不需要考虑异步,搜索按钮的提交和页面选择都可以直接制作url。
前端
需要修改两处:
- 使用
Html.BeginForm
- 翻页部分直接用
Url.Action
html
@using (Html.BeginForm("SearchIndex", "Home", FormMethod.Get))
{}
@Html.PagedListPager(Model.MyObject, page => Url.Action("SearchIndex", new { 查询参数 }))
后端
修改SearchIndex()
,将return PartialView("SearchIndex", 对象);
改为return View(对象)
即可。