zoukankan      html  css  js  c++  java
  • MVC学习(四)几种分页的实现(3)

      在这篇MVC学习(四)几种分页的实现(2)博文中,根据URL中传入的两个参数(页码数,首页、上一页、下一页、末页的标记符)来获得对应的分页数据,

    只是传入的参数太多,调用起来不太方便(标记符不能够写错,需要添加新的路由),因此,如果URL只传入页码数就太好,顺着这个思路,有了第三种分页方式。

    实现分页形式如下图所示。

      下面说说我的思路吧。

      为了在试图文件中呈现<input type="text" ...> ,我们需要写上代码@Html.TextBox(Asp.net MVC 3语法),为了呈现Lable,需要写@Html.Label,

    这里的@Html,有一个管理它的类 HtmlHelper。为了使用方便,我决定对HtmlHelper类进行扩展。

       考虑到有些页面不需要“上一页”,“下一页”之间的“100001”,因此,决定由两种呈现形式,一个是普通的分页,一个是带数字的分页,只有两种分页模式,新建一个枚举类型PageMode,代码如下

    /// <summary>
        /// 分页模式
        /// </summary>
        public enum PageMode
        {
            /// <summary>
            /// 普通分页模式
            /// </summary>
            Normal,
            /// <summary>
            /// 普通分页加数字分页
            /// </summary>
            Numeric
        }
    enum PageMode

      面向对象,对象总是很重要的,因此,页面对象是首先需要抽象出来的。

       我希望展现的形式是 “总共XX条记录,共XX页,当前第X页 首页 1 2... 上一页 下一页 末页”,想想这段话中,“记录数量”,“共多少页”,“第几页”,还有一条隐形“每页展示数据的大小”,因此,抽象出页面对象PagerInfo(TotalPageCount可以放入这个类中),代码如下。

        public class PagerInfo
        {
            public int RecordCount { get; set; }
    
            public int CurrentPageIndex { get; set; }
    
            public int PageSize { get; set; }
        }

      第一步,如何扩展HtmlHelper。

       首先,给大家看看微软如何@Html.Label的代码,看下面的截图

       在研究了这段代码后,就可以写一个普通的HtmlHelper扩展了,代码如下

     public static MvcHtmlString Pager(this HtmlHelper helper, string id, int currentPageIndex, int pageSize, int recordCount, object htmlAttributes, string className, PageMode mode)
            {
                TagBuilder builder = new TagBuilder("table");
                builder.IdAttributeDotReplacement = "_";
                builder.GenerateId(id);
                builder.AddCssClass(className);
                builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
                return builder.ToMvcHtmlString(TagRenderMode.Normal);
            }

      "string id"表示这个控件的id号,“int currentPageIndex”表示需要显示第几页数据的页码,

      “int pageSize"表示每页显示数据的大小,”object htmlAttributes“表示属性, ”string className“表示样式属性。

      看了我的HtmlHepler扩展代码,在与微软的原始代码比较以后,会发现我少了一行重要的代码,就是tagBuilder.SetInnerText(str);“,即控件在View

    的呈现形式。无论是asp.net WebForm页面的服务器控件,还是类似"<input type="text" runat="server">”控件,或者是asp.net MVC的@Html.Label,

    他们在页面的都是以字符串的形式展现。

      有了这个思路,写出普通的分页形式就比较简单了。

      我们只需要给TagBuilder给予正确的字符串就行了。

      1、首先获得总的记录数,总页数

        总记录数 int pageCount =Convert.ToInt32(Math.Ceiling((double)RecordCount / (double)PageSize));//获得总页数

       2、普通分页如何实现

       假设我们的url形式为 “http://localhost:11507/Home/FY3?page=2”,那么下一页的url形式便是“http://localhost:11507/Home/FY3?page=3”,因此,我们需要得到传来的绝对路径,不含任何参数。然后根据传来的当前页码数,判断是否有下一页,上一页,并且得到格式化后的url。

       这里我先理一理页码数如何传入HtmlHelper中的。

       首先,Controller从URL中获取CurrentPageIndex,然后放入PageInfo对象,并且获得分页数据(InfoSource);

       然后,我们将InfoSource与PageInfo两个对象放入一个泛型容器PagerQuery<T>,返回给View;

       最后,HtmlHelper根据View页面中的对象获得所需参数。

      

          现在回到HtmlHelper的扩展实现。

      获得我们需要ULR格式化字符串,如下代码。

      var url=new StringBuilder();

      url.Append(HttpContext.Current.Request.Url.AbsolutePath+"?page={0}");

      我希望展现的形式是 “总共XX条记录,共XX页,当前第X页 首页 上一页 下一页 末页”。现在开始拼字符串。

       var sb=new StringBuilder();

       sb.Append("<tr><td>");

       sb.AppendFormat("总共{0}条记录,共{1}页,当前第{2}页&nbsp;&nbsp;",RecordCount,pageCount,currentPageIndex);

      //RecordCount,currentPageIndex 值通过PagerInfo传递过来

      if(currentPageIndex==1{

        sb.Append("<span>首页</span>&nbsp;";)   //如果第一页 不需要给首页真实的链接
      }

      else{

        var url1=string.Format(url.ToString(),1);  //格式化URL 得到第一页的url   “http://localhost:11507/Home/FY3?page=1”

        sb.AppendFormat("<span><a href={0} 首页</a></span>&nbsp;",url1);

      }

      如何类推,可得到上一页、下一页、末页的链接。

        那么,如果上一页与下一页需要显示数字,怎么办呢? 这里,默认显示10个数字(如果页数不够,就按实际页数显示)

    private static string GetNumericPage(int currentPageIndex, int pageSize, int recordCount, int pageCount, string url)
            {
                var k = currentPageIndex / 10;
                var m = currentPageIndex % 10;
    
                var sb = new StringBuilder();
                if (currentPageIndex / 10 == pageCount / 10)//10个号码 为一组
                {
                    if (m == 0)
                    {
                        k--;
                        m = 10;
                    }
                    else
                        m = pageCount % 10;
                }
                else
                    m = 10;
             
                for (var i = k * 10 + 1; i <= k * 10 + m; i++)//如果是第1页 则 1...10 第11页,则11...20
                //for(int i=currentPageIndex;i<LastPage;i++)
                {
                    if (i == currentPageIndex)
    
                        sb.AppendFormat("<span><font color=red><b>{0}</b></font></span>&nbsp;", i);
                    else
                    {
                        var url1 = string.Format(url, i);
                        sb.AppendFormat("<span><a href={0}>{1}</a></span>&nbsp;", url1, i);
                    }
                }
    
                return sb.ToString();
            }
        }
    string GetNumericPage

        现在,可以得到扩展标签代码,如下

    public static MvcHtmlString Pager(this HtmlHelper helper, string id, int currentPageIndex, int pageSize, int recordCount, object htmlAttributes, string className, PageMode mode)
            {
                TagBuilder builder = new TagBuilder("table");
                builder.IdAttributeDotReplacement = "_";
                builder.GenerateId(id);
                builder.AddCssClass(className);
                builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
                builder.InnerHtml = GetNormalPage(currentPageIndex, pageSize, recordCount, mode);
                
                return builder.ToMvcHtmlString(TagRenderMode.Normal);
           
            }
    
            static MvcHtmlString ToMvcHtmlString(this TagBuilder tagBuilder, TagRenderMode renderMode)
            {
                return new MvcHtmlString(tagBuilder.ToString(renderMode));
            }

        得到分页字符串代码了,如下

    private static string GetNormalPage(int currentPageIndex, int PageSize, int RecordCount, PageMode mode)
            {
              
                int pageCount =Convert.ToInt32(Math.Ceiling((double)RecordCount / (double)PageSize));//获得总页数
                var url = new StringBuilder();
                url.Append(HttpContext.Current.Request.Url.AbsolutePath + "?page={0}");
             
                var sb = new StringBuilder();
                sb.Append("<tr><td>");
                sb.AppendFormat("总共{0}条记录,共{1}页,当前第{2}页&nbsp;&nbsp;", RecordCount, pageCount, currentPageIndex);
                if (currentPageIndex == 1)
                    sb.Append("<span>首页</span>&nbsp;");
                else
                {
                    var url1 = string.Format(url.ToString(), 1);
                    sb.AppendFormat("<span><a href={0}>首页</a></span>&nbsp;", url1);
                }
                if (currentPageIndex > 1)
                {
                    var url1 = string.Format(url.ToString(), currentPageIndex - 1);
                    sb.AppendFormat("<span><a href={0}>上一页</a></span>&nbsp;", url1);
                }
                else
                    sb.Append("<span>上一页</span>&nbsp;");
                if (mode == PageMode.Numeric)
                    sb.Append(GetNumericPage(currentPageIndex, PageSize, RecordCount, pageCount, url.ToString()));
                if (currentPageIndex < pageCount)
                {
                    string url1 = string.Format(url.ToString(), currentPageIndex + 1);
                    sb.AppendFormat("<span><a href={0}>下一页</a></span>&nbsp;", url1);
                }
                else
                    sb.Append("<span>下一页</span>&nbsp;");
    
                if (currentPageIndex == pageCount)
                    sb.Append("<span>末页</span>&nbsp;");
                else
                {
                    string url1 = string.Format(url.ToString(), pageCount);
                    sb.AppendFormat("<span><a href={0}>末页</a></span>&nbsp;", url1);
                }
                return sb.ToString();
            }
    GetNormalPage(int currentPageIndex, int PageSize, int RecordCount, PageMode mode)

       那么,承载数据的容器时什么呢,因为Model是会随时变化的(泛型类最佳实现),代码如下

    public class PagerQuery<T> : List<T>
        {
            public PagerQuery(PagerInfo pager, IEnumerable<T> source)
            {
                this.Pager = pager;
                int BeforePageIndex = pager.CurrentPageIndex - 1;
                if (BeforePageIndex < 0)
                {
                    BeforePageIndex = 1;
                }
                var entityList = source.Skip((BeforePageIndex) * pager.PageSize).Take(pager.PageSize);
                AddRange(entityList);
            }
            public PagerInfo Pager { get; set; }
        }

       Controller代码如下

    public ActionResult FY2(int? page)
            {
                LZSEntities _lzsDb=new LZSEntities();
                PagerInfo pager = new PagerInfo();
                pager.RecordCount = _lzsDb.MyTestPages.Count();
                pager.PageSize = 5;
                if (page == null)
                {
                    pager.CurrentPageIndex = 1;
                }
                else
                {
                    pager.CurrentPageIndex = Convert.ToInt32(page);
                }
    
                var result = _lzsDb.MyTestPages;
    
                IEnumerable<MyTestPages> info2 = result;
                var query = new PagerQuery<MyTestPages>(pager, info2);
                return View(query);
            }
    public ActionResult FY2(int? page)

       View代码如下

    @model MVCFY2.PageHelpers.PagerQuery<MVCFY2.Models.MyTestPages>
    @using MVCFY2.Models
    @using MVCFY2.PageHelpers;
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
        <head>
            <title>FY3</title>
        </head>
    <body>
    @* ReSharper disable once Html.Obsolete *@
         <table cellpadding="0" cellspacing="0" height="200px" width="300px" bordercolor="blue">
            <tr>
               
                <th height="30px">
                    序号
                </th>
            </tr>
            @foreach (var item in Model)
            {
                <tr>
                    <td align="center" height="30px">
                        @item.Id
                    </td>
                </tr>
            }
           
        </table>
        <div>
            
             <p> @Html.Pager("pager1", Model.Pager.CurrentPageIndex, Model.Pager.PageSize, Model.Pager.RecordCount, PageMode.Numeric)</p>
        </div>
    </body>
    </html>
    View

      VS 2010 MVC3,配置好数据库后,运行即可,源代码点此下载

      我感觉,第三种分页形式是很完美的,只是重复从第一页跳到最后一页再最后一页跳至第一页,分页缓慢,查看资源管理器,内存被占了很多,未曾释放,因此,

    希望各位可以告诉我高效的改进方法~~~

       

  • 相关阅读:
    Shell 基本运算符
    如何将mongo查询结果导出到文件中
    python如何将自己写的代码打包供他人使用
    json格式化
    如何在linux安装ruby2.2.2+
    如何对字符串进行码表替换转码--加密encode
    git基础
    如何创建redis集群
    linux安装python2.7
    如何在windows和linux搭建django环境
  • 原文地址:https://www.cnblogs.com/xianrongbin/p/3487807.html
Copyright © 2011-2022 走看看