环境:
win10
参考:
Bootstrap Pagination Dynamically In ASP.NET MVC
https://www.c-sharpcorner.com/article/bootstrap-pagination-dynamically-in-asp-net-mvc/
本文略去CRUD代码,默认读者可以连接数据库实现增删改查。之前写过:
ASP.NETMVC-简单例子-数据库查询+razor使用+项目发布_mvc怎么数据库搜索-CSDN博客
https://blog.csdn.net/pxy7896/article/details/139837179
效果
在模态框里插入一个具备分页功能的table,如下图所示:
翻页时保持主页面不动:
实现思路
首先,把这个可以分页的表格当成一个单独的组件,为它写一个展示类(ViewModel)。这个展示类应该包含页相关的信息(比如当前是第几页,一共多少页,每页多少条数据)。同时,为这个组件写前端,翻页的时候应该向后台发送异步请求,然后更新前端信息。
实现
ViewModel
在项目里新建一个文件夹ViewModel
,下面放一个类,此处称为MyObjectViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Demo.Models;
namespace Demo.ViewModel
{
public class MyObjectViewModel
{
public IEnumerable<MyObject> MyObject { get; set; }
public int ItemPerPage { get; set; }
public int CurrentPage { get; set; }
public int PageCount() {
return Convert.ToInt32(Math.Ceiling(MyObject.Count() / (double)ItemPerPage));
}
public IEnumerable<MyObject> PaginatedMyObject() {
int start = (CurrentPage - 1) * ItemPerPage;
return MyObject.OrderBy(b => b.id).Skip(start).Take(ItemPerPage);
}
}
}
其中,Demo是项目名称,MyObject是CRUD用到的类,各种公有属性与实际数据表中的列是一致的。
前端
新建一个视图,起名叫PageView
,
里面的内容如下:
@model WebApplication1.ViewModel.MyObjectViewModel
<div id="basicTable">
<table>
<thead>
<tr>
<th class="align-middle col-md-1">id</th>
<th class="align-middle col-md-1">name</th>
<th class="align-middle col-md-4">seq</th>
<th class="align-middle col-md-4">info</th>
<th class="align-middle col-md-2">stype</th>
</tr>
</thead>
<tbody>
@foreach (var bp in Model.PaginatedMyObject())
{
<tr>
<td class="align-middle">@bp.id</td>
<td class="align-middle">@bp.name</td>
<td class="align-middle">
@if (bp.seq.Length > 30)
{
@bp.seq.Substring(0, 30);
}
else
{
@bp.seq;
}
</td>
<td class="align-middle">@bp.info</td>
<td class="align-middle">@bp.stype</td>
</tr>
}
</tbody>
</table>
<ul class="pagination">
@for (int i = 1; i <= Model.PageCount(); i++)
{
<li class="@(i == Model.CurrentPage ? "page-item active" : "page-item")">
<a class="page-link" data-page="@i">@i</a>
</li>
}
</ul>
</div>
<script>
var btns = document.querySelectorAll("a");
btns.forEach(function (btn) {
btn.addEventListener("click", function (event) {
var page = btn.getAttribute("data-page");
// 发送异步请求
$.ajax({
url: '/Home/UpdateData',
type: 'POST',
data: {
page: page,
}, // 可以传递需要的参数
success: function (result) {
// 更新数据
$('#basicTable').html(result);
}
});
});
});
</script>
其中为页码<a>
增加了一个元素data-page
,用来记录是第几页。
主页面
主页面就是放置可分页表格的页面。下面是引入可分页表格时的写法:
<div>
@Html.Partial("PageView", Model.MyObjectViewModel)
</div>
主页面控制器
前面表格的前端发送ajax请求时使用的url是 /Home/UpdateData,所以在HomeController里写一个函数:
public ActionResult UpdateData(int page = 1) {
// 数据库的连接类
MyDbContext db = new MyDbContext();
MyObjectViewModel model = new MyObjectViewModel
{
ItemPerPage = 20,
MyObject = db.MyObjects.ToList(),
CurrentPage = page,
};
return PartialView("PageView", model);
}
其中关于数据库的连接方法,直接的文章里已经写好了,此处不再赘述。
这个函数是点击页码时用来更新数据的,那么,在载入主页面时,如果主页面是带对象的,那如何在初始化主页面时也初始化这个表格呢?
答案是要在主页面带的对象的类定义里,增加一个公有变量:
public MyObjectViewModel BasicPartViewModel { set; get; }
并且在初始化主页面的对象时,也初始化这个MyObjectViewModel,只不过CurrentPage写1罢了,参考下面:
using (MyDbContext db = new MyDbContext()){
//... 一些初始化主页面带的对象的代码
XXX.MyObjectViewModel = new MyObjectViewModel
{
ItemPerPage = 20,
MyObject = db.MyObject.ToList(),
CurrentPage = 1,
};
}
彩蛋
如果不需要写组件,只要单独的页面,就更简单了,甚至都不需要js。
注意在创建视图的时候去掉“创建为分部视图”的勾选。
前端
@model Demo.ViewModel.MyObjectViewModel
@{
ViewBag.Title = "PaginatedMyObject";
}
<table>
<!-- 内容略,与前面table一致 -->
</table>
<ul class="pagination">
@for (int i = 1; i <= Model.PageCount(); i++)
{
<li class="@(i == Model.CurrentPage ? "page-item active" : "page-item")">
<!-- 唯一区别是这一句 -->
<a class="page-link" href="@Url.Action("PaginatedMyObject", new { page = i })">@i</a>
</li>
}
</ul>
后端
同样需要创建MyObjectViewModel类,并且要在控制器里初始化,不同的是直接返回View,带MyObjectViewModel对象即可。
public ActionResult PaginatedMyObject(int page = 1) {
// 与前面一致,也是从数据库初始化MyObjectViewModel
MyObjectViewModel model = new MyObjectViewModel....
// 直接return View就行
return View(model);
}