Asp.Net MVC实现分页、检索、排序的代码展示
很多时候需要这样的功能,对表格进行分页、排序和检索。这个有很多实现的方式,有现成的表格控件、用前端的mvvm,用户控件。但很多时候看着很漂亮的东西你想进一步控制的时候却不那么如意。这里自己实现一次,功能不是高大全,但求一个清楚明白,也欢迎园友拍砖。前端是bootstraP3+jPaginate,后台基于membership。没什么难点。
先上效果图。
分页其实就是处理好 每页项目数、总项目数、总页数、当前页。为了方便复用,就先从仓库开始说起。
一、建立仓库
1.定义Ipager接口,需要分页的模型仓库继承这个接口
namespace PRotal.Model.Abstract{
/// summary>
/// 分页处理 /// /summary>
public interface IPager {
/// summary>
/// 每页项目数 /// /summary>
/// value>
The page ITem count./value>
int PageitemCount {
get;
set;
}
/// summary>
/// 总页数 /// /summary>
/// value>
The totoal page./value>
int TotoalPage {
get;
}
/// summary>
/// 显示的页数 /// /summary>
/// value>
The display page./value>
int DisplayPage {
get;
set;
}
/// summary>
/// 满足条件的总数目 /// /summary>
int totalItem {
get;
set;
}
}
}
2.定义IUsersRepository,主要处理User 相关的业务逻辑。Find函数是主要的查询方法,order表示顺反排序。
public interface IUsersRepository : IPager {
/// summary>
/// Post list /// /summary>
/// param name="order">
Order exPression/param>
/// param name="filter">
Filter expression/param>
/// param name="skip">
Records to skip/param>
/// param name="take">
Records to take/param>
/// returns>
List of users/returns>
IEnumerableUser>
Find(int order=0,string filter="", int skip = 0, int take = 10);
/// summary>
/// Get single post /// /summary>
/// param name="name">
User id/param>
/// returns>
User object/returns>
User FindByName(string name);
/// summary>
/// Add new user /// /summary>
/// param name="user">
blog user/param>
/// returns>
Saved user/returns>
User Add(User user);
/// summary>
/// Update user /// /summary>
/// param name="user">
User to update/param>
/// returns>
True on success/returns>
bool Update(User user);
/// summary>
/// Save user profile /// /summary>
/// param name="user">
BLOG user/param>
/// returns>
True on success/returns>
bool SaveProfile(User user);
/// summary>
/// Delete user /// /summary>
/// param name="userName">
User ID/param>
/// returns>
True on success/returns>
bool Remove(string userName);
}
二、仓库的实现和绑定
主要方法:Membership的中的User和我们自定义的不一样,所以存在一个转换
public class UsersRepository : IUsersRepository {
/// summary>
/// The _user list /// /summary>
private ListUser>
_userList = new ListUser>
();
/// summary>
/// The _page item count /// /summary>
private int _pageItemCount;
/// summary>
/// The _display page /// /summary>
private int _displayPage;
/// summary>
/// The _usercount /// /summary>
private int _usercount;
/// summary>
/// The _total item /// /summary>
private int _totalItem;
/// summary>
/// 标记是否有查询条件 没有的话则返回全部数目 /// /summary>
private FuncUser, bool>
_func;
/// summary>
/// Gets or sets the users. /// /summary>
/// value>
The users./value>
public ListUser>
Users {
get {
int count;
VAR usercollection = Membership.GetAllUsers(0, 999, out count);
if (count == _usercount) return _userList;
_usercount = count;
var members = usercollection.CastmembershipUser>
().ToList();
foreach (var membershipUser in members)//这里存在一个转换 {
_userList.Add(new User {
Email = membershipUser.Email, UserName = membershipUser.UserName, //roles password }
);
}
return _userList;
}
set {
_userList = value;
}
}
//查询public IEnumerableUser>
Find(int order = 0, string filter = "", int skip = 0, int take = 10) {
if (take == 0) take = Users.Count;
//过滤 _func = string.IsNullOrEmpty(filter) ? (FuncUser, bool>
) (n =>
n.UserName != "") : (n =>
n.UserName.Contains(filter));
var users = Users.Where(_func).ToList();
//更新总数目 _totalItem = users.Count;
users = order == 0 ? users.OrderBy(n =>
n.UserName).ToList() : users.OrderByDescending(n =>
n.UserName).ToList();
return users.Skip(skip).Take(take);
}
/// summary>
/// 每页项目数 /// /summary>
/// value>
The page item count./value>
public int PageItemCount {
get {
if (_pageItemCount == 0) {
_pageItemCount = Protalconfig.UserPageItemCount;
}
return _pageItemCount;
}
set {
_pageItemCount = value;
}
}
/// summary>
/// 总页数 /// /summary>
/// value>
The totoal page./value>
public int TotoalPage {
get {
var page = (int) Math.Ceiling((double) TotalItem/PageItemCount);
return page==0?1:page;
}
}
/// summary>
/// 显示的页数 /// /summary>
/// value>
The display page./value>
public int DisplayPage {
get {
if (_displayPage == 0) {
_displayPage = ProtalConfig.UserDisplayPage;
}
return _displayPage;
}
set {
_displayPage = value;
}
}
/// summary>
/// 满足条件的总数目 保持更新 /// /summary>
/// value>
The total item./value>
public int TotalItem {
get {
if (_func == null) _totalItem = Users.Count;
return _totalItem;
}
set {
_totalItem = value;
}
}
}
ProtalConfig.UserDisplayPage 这里是通过配置实现一个默认页数,让用户可以再webconfig中更改行列的数目。
public static int UserPageItemCount {
get {
if (_userPageItemCount == 0) {
_userPageItemCount = WebConfigurationManager.AppSettings["UserPageItemCount"] != null ? Convert.ToInt16(WebConfigurationManager.AppSettings["UserPageItemCount"]) : 5;
}
return _userPageItemCount;
}
set {
_userPageItemCount = value;
}
}
再进行绑定:
_kernel.BindIUsersRepository>
().ToUsersRepository>
();
三、控制器部分
我们需要两个页面,一个主页面Index,一个负责局部刷新的部分视图 UserTable
下面是主要的方法,主要逻辑都在在仓库中处理了。
[Authorize] public class UserManagerController : Controller {
/// summary>
/// The _repository /// /summary>
private readonly IUsersRepository _repository;
/// summary>
/// Initializes a new instance of the see cref="UserManagerController"/>
class. /// /summary>
/// param name="iRepository">
The i repository./param>
public UserManagerController(IUsersRepository iRepository) {
_repository = iRepository;
}
/// summary>
/// Indexes the sPEcified page index. /// /summary>
/// param name="pageIndex">
Index of the page./param>
/// returns>
ActionResult./returns>
public ActionResult Index(int pageIndex=1) {
ViewBag.DisplayPage = _repository.DisplayPage;
pageIndex = HandlePageindex(pageIndex);
//支持地址栏直接分页 ViewBag.currentPage = pageIndex;
return View();
}
/// summary>
/// Users table. 分页模块 /// /summary>
/// param name="pageIndex">
Index of the page./param>
/// param name="order">
The order./param>
/// param name="filter">
The filter str./param>
/// returns>
ActionResult./returns>
public ActionResult UserTable(int pageIndex = 1, int order = 0, string filter = "") {
pageIndex = HandlePageindex(pageIndex);
var skip = (pageIndex - 1) * _repository.PageItemCount;
var users = _repository.Find(order,filter, skip, _repository.PageItemCount);
//总用户数 ViewBag.TotalUser = _repository.TotalItem;
//总页数 ViewBag.TotalPageCount = _repository.TotoalPage;
;
return PartialView(users);
}
/// summary>
/// 处理页数 防止过大或过小 /// /summary>
/// param name="index">
/param>
/// returns>
/returns>
private int HandlePageindex(int index) {
var totoalpage = _repository.TotoalPage;
if (index == 0) return 1;
return index >
totoalpage ? totoalpage : index;
}
}
四、视图部分HtML jquery
1.Index.cshtml
script src="~/Scripts/form.js">
/script>
p class="container">
h4 class="bottomline">
管理用户/h4>
p>
button data-target="#adduser" id="adduserBT" data-toggle="modal" class="btn btn-info btn-hover">
新增用户/button>
button class="btn btn-danger" id="deluser">
删除/button>
span class="errorinfo">
/span>
input type="seArch" class="pull-right" id="usersearch" placeholder="搜索"/>
/p>
p id="userpart">
@Html.Action("UserTable",new{
pageIndex=ViewBag.CurrentPage}
) /p>
p id="userpager">
/p>
input type="hidden" id="dispalypage" value="@ViewBag.DisplayPage"/>
input type="hidden" id="page" value="@ViewBag.CurrentPage"/>
input type="hidden" id="currentpage" value="@ViewBag.CurrentPage"/>
/p>
p class="modal fade adduserbox"id="adduser" tabindex="1" role="dialog" aria-hidden="true">
p class="modal-content">
p class="modal-header">
button type="button" class="close" data-dismiss="modal" aria-hidden="true" >
×/button>
h4 class="modal-title">
Add new User/h4>
/p>
p class="modal-body">
@{
Html.RenderAction("Create","UserManager");
}
/p>
/p>
/p>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")}
2.UserTable.cshtml,角色部分还未处理,这个表格更新之后,也会更新满足条件的用户数和新的总页数,触发Jpaginate重新分页一次。
@model IEnumerableProtal.Model.Data.User.User>
table id="usertable" class="table table-striped table-condensed table-hover table-bordered">
tr>
th>
input type="checkbox" id="allcheck" />
label for="allcheck">
全选/label>
/th>
th>
a href="#" id="usersort" data-order="0" class="glyphicon-sort">
名称/a>
/th>
th>
角色/th>
th>
E-mail/th>
/tr>
tbody>
@foreach (var item in Model) {
tr>
td>
input type="checkbox" data-id="@item.UserName" />
/td>
td>
a>
@item.UserName/a>
/td>
td>
@Html.Raw(item.Role) /td>
td>
@item.Email/td>
/tr>
}
/tbody>
tfoot>
tr>
td colspan="4">
span>
@Html.Raw("共"+ViewBag.TotalUser+"人")/span>
@*span>
@ViewBag.TotalPageCount/span>
*@ /td>
/tr>
/tfoot>
/table>
input type="hidden" id="totoalpage" value="@ViewBag.TotalPageCount"/>
3.脚本
其中用到的像checkall,infoshow 都是自己扩展的一些简单的方法,用于全选和提示。
$(function () {
var options = {
dataType: 'json', success: processJson }
;
pageagin($("#totoalpage").val());
//分页 function pageagin(totalcount) {
$("#userpager").paginate({
count: totalcount, start: $("#page").val(), dispaly: $("#dispalypage").val(), boder: false, border_color: '#fff',//自己调整样式。 text_color: 'black', background_color: 'none', border_hover_color: '#ccc', text_hover_color: '#000', background_hover_color: '#fff', images: false, mouse: 'press', onChange: function (page) {
//翻页 paging(page);
$("#currentpage").val(page);
}
}
);
}
//分页更新 function paging(page) {
$.post("/Users/UserTable", {
pageIndex: page, order: $("#userpart").attr("data-order"), filter: $.trim($("#usersearch").val()) }
, function (data) {
$("#userpart").html(data);
}
);
}
//排序 $("#usersort").live("click",function () {
$("#userpart").triggerdataOrder();
paging( $("#currentpage").val());
}
);
//搜索 $("#usersearch").keyup(function() {
paging($("#currentpage").val());
pageagin($("#totoalpage").val());
}
);
//处理form $("#userForm").submit(function () {
$(this).ajaxSubmit(options);
return false;
}
);
function processJson(data) {
if (data == 1) {
location.reload();
}
else {
alert("添加失败");
}
}
//高亮 $("#unav li:eq(0)").addClass("active");
$("#adnav li:eq(2)").addClass("active");
//全选/全不选 $("#allcheck").checkall($("#usertable tbody input[type='checkbox']"));
//删除用户 $("#deluser").click(function () {
var checks = $("#usertable tbody input[type='checkbox']:checked");
var lens = checks.length;
if (lens == 0) {
$.infoShow("未选择删除对象",0);
return false;
}
if (confirm("确定要删除所选中用户?")) {
for (var i = 0;
i lens;
i++) {
var $chek = checks.eq(i);
var id = $chek.attr("data-id");
var tr = $chek.parent().parent();
$.post("Users/DeleteUser", {
id: id }
, function (data) {
if (data == 1) {
tr.fadeOut();
$.infoShow("删除成功", 1);
}
else {
$.infoShow("删除失败", 0);
}
}
);
}
}
return true;
}
);
// 增加用户 $("#adduserbt").click(function() {
$(".modal-header").show();
}
);
}
)到这里就是全部的代码,供大家和自己参考。
再给大家看两个效果图,一个是kendoui的grid,一个是Angular做的分页。后面有机会给大家介绍。
Kendo- Grid
Kendo和MVC框架融合度比较高,它的核心代码如下:
@model IEnumerableKendo.Mvc.Examples.Models.ProductViewModel>
@(Html.Kendo().Grid(Model) .Name("Grid") .Columns(columns =>
{
columns.Bound(p =>
p.ProductID).Groupable(false);
columns.Bound(p =>
p.ProductName);
columns.Bound(p =>
p.UnitPrice);
columns.Bound(p =>
p.UnitsInStock);
}
) .Pageable() .Sortable() .Scrollable() .Filterable() .DataSource(dataSource =>
dataSource .Ajax() .Serveroperation(false) ))AngularJs 核心还是调用封装好的API函数,相当于上面的仓库中的方法,然后通过模型绑定。
总结一下:自己实现代码量比较多,功能不全,有重复造轮子的感觉,但可以较好的控制,基本够用;kendo的方式感觉高大全,用熟了开发速度快。就是多一些引用,且需要担心kendoui和其他的ui框架会有冲突。前端MVVM的方式我了解还不够深,感觉前端脚本的代码量也蛮多,效果不错。但生成的html代码很少。上面这个表格。chrome F12或者右键查看源码都是下面这样子的:
主要的就一个p
p data-ng-app="blogAdmin" data-ng-view="" id="ng-view">
/p>
自我保护倒是蛮好,也就是SEO可能有问题。应该还有更好的方式,猿友们指点指点。
html>
head>
title>
Name of the blog (Admin)/title>
link rel="shortcut icon" href="/pics/blogengine.ico" type="image/x-icon" />
meta charset="utf-8" />
meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1" />
meta name="apple-mobile-web-app-capable" content="yes" />
meta name="apple-mobile-web-app-status-bar-style" content="black" />
meta name="format-detection" content="telephone=no" />
meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
link href="/Content/bootstrap/bootstrap.css" rel="stylesheet"/>
link href="/Content/bootstrap/bootstrap-theme.css" rel="stylesheet"/>
link href="/Content/toastr.css" rel="stylesheet"/>
link href="/Content/font-awesome.css" rel="stylesheet"/>
link href="/Content/editor.css" rel="stylesheet"/>
link href="/Content/app.css" rel="stylesheet"/>
script type="text/javascript">
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
var msViewportStyle = document.createElement("style");
var mq = "@-ms-viewport{
width:auto!important}
";
msViewportStyle.appendChild(document.createTextNode(mq));
document.getelementsbytagname("head")[0].appendChild(msViewportStyle);
}
/script>
/head>
body>
script type="text/javascript">
var SiteVars = {
ApplicationRelativeWebroot: '/', RelativeWebRoot: '/', BlogInstanceId: '96d5b379-7e1d-4dac-a6ba-1e50db561b04', UserName: 'admin', UserRights: ['ViewDetailedErrorMessages', 'AccessAdminPages', 'AccessAdminSettingsPages', 'ManageWidgets', 'ViewPublicComments', 'ViewUnmoderatedComments', 'CreateComments', 'ModerateComments', 'ViewPublicPosts', 'ViewUnpublishedPosts', 'CreateNewPosts', 'EditOwnPosts', 'EditOtherUsersPosts', 'DeleteOwnPosts', 'DeleteOtherUsersPosts', 'PublishOwnPosts', 'PublishOtherUsersPosts', 'ViewPublicPages', 'ViewUnpublishedPages', 'CreateNewPages', 'EditOwnPages', 'ViewRatingsOnPosts', 'SubmitRatingsOnPosts', 'ViewRoles', 'CreateNewRoles', 'EditRoles', 'DeleteRoles', 'EditOwnRoles', 'EditOtherUsersRoles', 'CreateNewUsers', 'DeleteUserSelf', 'DeleteUsersOtherThanSelf', 'EditOwnUser', 'EditOtherUsers'], AbsoluteWebRoot: 'http://localhost:53265/', Version: 'BlogEngine.NET ' + '2.9.1.0', IsPrimary: 'True', IsAdmin: 'True', AppRoot: function (url) {
window.location = '/' + url;
return false;
}
, BlogRoot: function (url) {
window.location = '/' + url;
}
}
;
/script>
script type="text/javascript" src="admin.res.axd">
/script>
p id="container" class="app-wrapper ltr">
p data-ng-app="blogAdmin" data-ng-view="" id="ng-view">
/p>
/p>
script src="/scripts/jquery-2.0.3.js">
/script>
script src="/scripts/jquery.validate.js">
/script>
script src="/scripts/jquery.form.js">
/script>
script src="/scripts/toastr.js">
/script>
script src="/Scripts/angular.min.js">
/script>
script src="/Scripts/angular-route.min.js">
/script>
script src="/Scripts/angular-aniMATE.min.js">
/script>
script src="/Scripts/angular-sanitize.min.js">
/script>
script src="/admin/be-grid.js">
/script>
script src="/admin/app.js">
/script>
script src="/admin/controllers/dashboard.js">
/script>
script src="/admin/controllers/blogs.js">
/script>
script src="/admin/controllers/posts.js">
/script>
script src="/admin/controllers/pages.js">
/script>
script src="/admin/controllers/tags.js">
/script>
script src="/admin/controllers/categories.js">
/script>
script src="/admin/controllers/comments.js">
/script>
script src="/admin/controllers/users.js">
/script>
script src="/admin/controllers/roles.js">
/script>
script src="/admin/controllers/profile.js">
/script>
script src="/admin/controllers/settings.js">
/script>
script src="/admin/controllers/packages.js">
/script>
script src="/admin/controllers/common.js">
/script>
script src="/admin/services.js">
/script>
script src="/scripts/bootstrap.js">
/script>
script src="/scripts/moment.js">
/script>
/body>
/html>
PS:这个东西没什么难度,逻辑都在仓库中,要源码的同学我后续分离出来了再贴出来。当然这个又很多方式,我也不是要秀什么框架,但我目前项目的需求是要这么分开的。一个控制器是可用解决所有问题,但我其他模型也要分页又要便于测试难道我都写在控制器中吗?
以上就是Asp.Net MVC实现分页、检索、排序的代码展示的详细内容,更多请关注其它相关文章!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Asp.Net MVC实现分页、检索、排序的代码展示
本文地址: https://pptw.com/jishu/592669.html
