zoukankan      html  css  js  c++  java
  • Asp.Net MVC 分页、检索、排序整体实现

    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>
            IEnumerable<User> 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 List<User> _userList = new List<User>();
           /// <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 Func<User, bool> _func;
    
            /// <summary>
            /// Gets or sets the users.
            /// </summary>
            /// <value>The users.</value>
            public List<User> Users
           {
               get
               {
                   int count;
                   var usercollection = Membership.GetAllUsers(0, 999, out count);
                   if (count == _usercount) return _userList;
                   _usercount = count;
                   var members = usercollection.Cast<MembershipUser>().ToList();
                   foreach (var membershipUser in members)//这里存在一个转换
                   {
                       _userList.Add(new User
                       {
                           Email = membershipUser.Email,
                           UserName = membershipUser.UserName,
                           //roles password
                       });
                   }
                   return _userList;
               }
               set { _userList = value; }
           }
         
    //查询
    public IEnumerable<User> Find(int order = 0, string filter = "", int skip = 0, int take = 10) { if (take == 0) take = Users.Count;
    //过滤 _func
    = string.IsNullOrEmpty(filter) ? (Func<User, 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中更改行列的数目。
     View Code

     再进行绑定:

        _kernel.Bind<IUsersRepository>().To<UsersRepository>();

    三、控制器部分

      我们需要两个页面,一个主页面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>
    <div 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>
        <div id="userpart">
              @Html.Action("UserTable",new{pageIndex=ViewBag.CurrentPage})
        </div>
        <div  id="userpager"></div>
        <input type="hidden" id="dispalypage" value="@ViewBag.DisplayPage"/>
        <input type="hidden" id="page" value="@ViewBag.CurrentPage"/>
        <input type="hidden" id="currentpage" value="@ViewBag.CurrentPage"/>
    
    </div>
    <div class="modal fade adduserbox"id="adduser" tabindex="1" role="dialog" aria-hidden="true">
        <div class="modal-content">
            <div class="modal-header">
                 <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >&times;</button>
                 <h4 class="modal-title">Add new User</h4>
            </div>
            <div class="modal-body">
               @{
                   Html.RenderAction("Create","UserManager");
                }
            </div>
        </div>
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    复制代码

    2.UserTable.cshtml,角色部分还未处理,这个表格更新之后,也会更新满足条件的用户数和新的总页数,触发Jpaginate重新分页一次。

    复制代码
    @model IEnumerable<Protal.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 都是自己扩展的一些简单的方法,用于全选和提示。

     View Code

    到这里就是全部的代码,供大家和自己参考。

    再给大家看两个效果图,一个是kendoui的grid,一个是Angular做的分页。后面有机会给大家介绍。

    Kendo- Grid

     Kendo和MVC框架融合度比较高,它的核心代码如下:

     View Code

    AngularJs 核心还是调用封装好的API函数,相当于上面的仓库中的方法,然后通过模型绑定。

     总结一下:自己实现代码量比较多,功能不全,有重复造轮子的感觉,但可以较好的控制,基本够用;kendo的方式感觉高大全,用熟了开发速度快。就是多一些引用,且需要担心kendoui和其他的ui框架会有冲突。前端MVVM的方式我了解还不够深,感觉前端脚本的代码量也蛮多,效果不错。但生成的html代码很少。上面这个表格。chrome F12或者右键查看源码都是下面这样子的:

      主要的就一个div 

     <div data-ng-app="blogAdmin" data-ng-view="" id="ng-view"></div>

    自我保护倒是蛮好,也就是SEO可能有问题。应该还有更好的方式,猿友们指点指点。

     View Code

      希望对你有帮助,Tks!

     
     
    分类: MVC
  • 相关阅读:
    暑假周总结02
    音乐播放器
    setInterval、控制停止和继续
    暑假周总结01
    ul li、a标签的下划线
    innerHTML、document获取对象、className修改样式
    领扣(LeetCode)N叉树的层序遍历 个人题解
    领扣(LeetCode)两句话中的不常见单词 个人题解
    领扣(LeetCode)二叉树的中序遍历 个人题解
    领扣(LeetCode)用队列实现栈 个人题解
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3715375.html
Copyright © 2011-2022 走看看