ASP.NET MVC分页库(一)【基础类库】

信仰,就像恐惧和爱一样,是一种决定我们人生走向的力量。


实体,接口,实现类

 public interface IPagedList
    {
        int PageCount { get; }
        int TotalItemCount { get; }
        int PageIndex { get; }
        int PageNumber { get; }
        int PageSize { get; }
        bool HasPreviousPage { get; }
        bool HasNextPage { get; }
        bool IsFirstPage { get; }
        bool IsLastPage { get; }
        int ItemStart { get; }
        int ItemEnd { get; }
    }

    public interface IPagedList<out T> : IPagedList, IEnumerable<T>
    {
    }

public class PagedList<T> : List<T>, IPagedList<T>
    {
        public PagedList(IEnumerable<T> source, int index, int pageSize, int? totalCount = null)
            : this(source.AsQueryable(), index, pageSize, totalCount)
        {
        }

        public PagedList(IQueryable<T> source, int index, int pageSize, int? totalCount = null)
        {
            if (index < 0)
                throw new ArgumentOutOfRangeException("index", "值不能低于0");
            if (pageSize < 1)
                throw new ArgumentOutOfRangeException("pageSize", "值不能低于1.");

            if (source == null)
                source = new List<T>().AsQueryable();

            int realTotalCount = source.Count();

            PageSize = pageSize;
            PageIndex = index;
            TotalItemCount = totalCount.HasValue ? totalCount.Value : realTotalCount;
            PageCount = TotalItemCount > 0 ? (int) Math.Ceiling(TotalItemCount/(double) PageSize) : 0;

            HasPreviousPage = (PageIndex > 0);
            HasNextPage = (PageIndex < (PageCount - 1));
            IsFirstPage = (PageIndex <= 0);
            IsLastPage = (PageIndex >= (PageCount - 1));

            ItemStart = PageIndex*PageSize + 1;
            ItemEnd = Math.Min(PageIndex*PageSize + PageSize, TotalItemCount);

            if (TotalItemCount <= 0)
                return;

            if (realTotalCount != TotalItemCount)
                AddRange(source.Take(PageSize));
            else
                AddRange(source.Skip(PageIndex*PageSize).Take(PageSize));
        }

        #region IPagedList Members

        public int PageCount { get; private set; }
        public int TotalItemCount { get; private set; }
        public int PageIndex { get; private set; }

        public int PageNumber
        {
            get { return PageIndex + 1; }
        }

        public int PageSize { get; private set; }
        public bool HasPreviousPage { get; private set; }
        public bool HasNextPage { get; private set; }
        public bool IsFirstPage { get; private set; }
        public bool IsLastPage { get; private set; }
        public int ItemStart { get; private set; }
        public int ItemEnd { get; private set; }

        #endregion
    }

Pager.cs类:

  public class Pager : IHtmlString
    {
        private readonly int currentPage;
        private readonly HtmlHelper htmlHelper;
        private readonly int pageSize;
        protected readonly PagerOptions pagerOptions;
        private int totalItemCount;

        public Pager(HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount)
        {
            this.htmlHelper = htmlHelper;
            this.pageSize = pageSize;
            this.currentPage = currentPage;
            this.totalItemCount = totalItemCount;
            pagerOptions = new PagerOptions();
        }

        public virtual string ToHtmlString()
        {
            PaginationModel model = BuildPaginationModel(GeneratePageUrl);

            if (!String.IsNullOrEmpty(pagerOptions.DisplayTemplate))
            {
                string templatePath = string.Format("DisplayTemplates/{0}", pagerOptions.DisplayTemplate);
                return htmlHelper.Partial(templatePath, model).ToHtmlString();
            }
            else
            {
                var sb = new StringBuilder();

                foreach (PaginationLink paginationLink in model.PaginationLinks)
                {
                    if (paginationLink.Active)
                    {
                        if (paginationLink.IsCurrent)
                        {
                            sb.AppendFormat("<span class=\"current\">{0}</span>", paginationLink.DisplayText);
                        }
                        else if (!paginationLink.PageIndex.HasValue)
                        {
                            sb.AppendFormat(paginationLink.DisplayText);
                        }
                        else
                        {
                            var linkBuilder = new StringBuilder("<a");

                            if (pagerOptions.AjaxOptions != null)
                                foreach (var ajaxOption in pagerOptions.AjaxOptions.ToUnobtrusiveHtmlAttributes())
                                    linkBuilder.AppendFormat(" {0}=\"{1}\"", ajaxOption.Key, ajaxOption.Value);

                            linkBuilder.AppendFormat(" href=\"{0}\" title=\"{1}\">{2}</a>", paginationLink.Url,
                                paginationLink.DisplayTitle, paginationLink.DisplayText);

                            sb.Append(linkBuilder.ToString());
                        }
                    }
                    else
                    {
                        if (!paginationLink.IsSpacer)
                        {
                            sb.AppendFormat("<span class=\"disabled\">{0}</span>", paginationLink.DisplayText);
                        }
                        else
                        {
                            sb.AppendFormat("<span class=\"spacer\">{0}</span>", paginationLink.DisplayText);
                        }
                    }
                }
                return sb.ToString();
            }
        }

        public Pager Options(Action<PagerOptionsBuilder> buildOptions)
        {
            buildOptions(new PagerOptionsBuilder(pagerOptions));
            return this;
        }

        public virtual PaginationModel BuildPaginationModel(Func<int, string> generateUrl)
        {
            int pageCount;
            if (pagerOptions.UseItemCountAsPageCount)
            {
                // 直接从总项计数而不是计算设置页数。 然后根据pageCount和pageSize计算totalItemCount;
                pageCount = totalItemCount;
                totalItemCount = pageCount*pageSize;
            }
            else
            {
                pageCount = (int) Math.Ceiling(totalItemCount/(double) pageSize);
            }

            var model = new PaginationModel
            {
                PageSize = pageSize,
                CurrentPage = currentPage,
                TotalItemCount = totalItemCount,
                PageCount = pageCount
            };

            //第一页
            if (pagerOptions.DisplayFirstPage)
            {
                model.PaginationLinks.Add(new PaginationLink
                {
                    Active = (currentPage > 1 ? true : false),
                    DisplayText = pagerOptions.FirstPageText,
                    DisplayTitle = pagerOptions.FirstPageTitle,
                    PageIndex = 1,
                    Url = generateUrl(1)
                });
            }

            // 上一页
            if (!pagerOptions.HidePreviousAndNextPage)
            {
                string previousPageText = pagerOptions.PreviousPageText;
                model.PaginationLinks.Add(currentPage > 1
                    ? new PaginationLink
                    {
                        Active = true,
                        DisplayText = previousPageText,
                        DisplayTitle = pagerOptions.PreviousPageTitle,
                        PageIndex = currentPage - 1,
                        Url = generateUrl(currentPage - 1)
                    }
                    : new PaginationLink {Active = false, DisplayText = previousPageText});
            }

            int start = 1;
            int end = pageCount;
            int nrOfPagesToDisplay = pagerOptions.MaxNrOfPages;

            if (pageCount > nrOfPagesToDisplay)
            {
                int middle = (int) Math.Ceiling(nrOfPagesToDisplay/2d) - 1;
                int below = (currentPage - middle);
                int above = (currentPage + middle);

                if (below < 2)
                {
                    above = nrOfPagesToDisplay;
                    below = 1;
                }
                else if (above > (pageCount - 2))
                {
                    above = pageCount;
                    below = (pageCount - nrOfPagesToDisplay + 1);
                }

                start = below;
                end = above;
            }

            if (start > 1)
            {
                model.PaginationLinks.Add(new PaginationLink
                {
                    Active = true,
                    PageIndex = 1,
                    DisplayText = "1",
                    Url = generateUrl(1)
                });
                if (start > 3)
                {
                    model.PaginationLinks.Add(new PaginationLink
                    {
                        Active = true,
                        PageIndex = 2,
                        DisplayText = "2",
                        Url = generateUrl(2)
                    });
                }
                if (start > 2)
                {
                    model.PaginationLinks.Add(new PaginationLink {Active = false, DisplayText = "...", IsSpacer = true});
                }
            }

            for (int i = start; i <= end; i++)
            {
                if (i == currentPage || (currentPage <= 0 && i == 1))
                {
                    model.PaginationLinks.Add(new PaginationLink
                    {
                        Active = true,
                        PageIndex = i,
                        IsCurrent = true,
                        DisplayText = i.ToString()
                    });
                }
                else
                {
                    model.PaginationLinks.Add(new PaginationLink
                    {
                        Active = true,
                        PageIndex = i,
                        DisplayText = i.ToString(),
                        Url = generateUrl(i)
                    });
                }
            }

            if (end < pageCount)
            {
                if (end < pageCount - 1)
                {
                    model.PaginationLinks.Add(new PaginationLink {Active = false, DisplayText = "...", IsSpacer = true});
                }
                if (end < pageCount - 2)
                {
                    model.PaginationLinks.Add(new PaginationLink
                    {
                        Active = true,
                        PageIndex = pageCount,
                        DisplayText = (pageCount).ToString(),
                        Url = generateUrl(pageCount)
                    });
                }
            }

            //下一页
            if (!pagerOptions.HidePreviousAndNextPage)
            {
                string nextPageText = pagerOptions.NextPageText;
                model.PaginationLinks.Add(currentPage < pageCount
                    ? new PaginationLink
                    {
                        Active = true,
                        PageIndex = currentPage + 1,
                        DisplayText = nextPageText,
                        DisplayTitle = pagerOptions.NextPageTitle,
                        Url = generateUrl(currentPage + 1)
                    }
                    : new PaginationLink {Active = false, DisplayText = nextPageText});
            }

            // 最后一页
            if (pagerOptions.DisplayLastPage)
            {
                model.PaginationLinks.Add(new PaginationLink
                {
                    Active = (currentPage < pageCount ? true : false),
                    DisplayText = pagerOptions.LastPageText,
                    DisplayTitle = pagerOptions.LastPageTitle,
                    PageIndex = pageCount,
                    Url = generateUrl(pageCount)
                });
            }

            // Ajax选项
            if (pagerOptions.AjaxOptions != null)
            {
                model.AjaxOptions = pagerOptions.AjaxOptions;
            }

            model.Options = pagerOptions;
            return model;
        }

        protected virtual string GeneratePageUrl(int pageNumber)
        {
            ViewContext viewContext = htmlHelper.ViewContext;
            RouteValueDictionary routeDataValues = viewContext.RequestContext.RouteData.Values;
            RouteValueDictionary pageLinkValueDictionary;

            //当页码等于1时,避免错误
            if (pageNumber == 1 && !pagerOptions.AlwaysAddFirstPageNumber)
            {
                pageLinkValueDictionary = new RouteValueDictionary(pagerOptions.RouteValues);

                if (routeDataValues.ContainsKey(pagerOptions.PageRouteValueKey))
                {
                    routeDataValues.Remove(pagerOptions.PageRouteValueKey);
                }
            }
            else
            {
                pageLinkValueDictionary = new RouteValueDictionary(pagerOptions.RouteValues)
                {
                    {pagerOptions.PageRouteValueKey, pageNumber}
                };
            }

            //确保我们得到正确的路由,确保指定控制器和动作。
            if (!pageLinkValueDictionary.ContainsKey("controller") && routeDataValues.ContainsKey("controller"))
            {
                pageLinkValueDictionary.Add("controller", routeDataValues["controller"]);
            }

            if (!pageLinkValueDictionary.ContainsKey("action") && routeDataValues.ContainsKey("action"))
            {
                pageLinkValueDictionary.Add("action", routeDataValues["action"]);
            }

            // 修复字典,如果它有数组。
            pageLinkValueDictionary = pageLinkValueDictionary.FixListRouteDataValues();

            // 'Render' 虚拟路径。
            VirtualPathData virtualPathForArea = RouteTable.Routes.GetVirtualPathForArea(viewContext.RequestContext,
                pageLinkValueDictionary);

            return virtualPathForArea == null ? null : virtualPathForArea.VirtualPath;
        }
    }

    public class Pager<TModel> : Pager
    {
        private HtmlHelper<TModel> htmlHelper;

        public Pager(HtmlHelper<TModel> htmlHelper, int pageSize, int currentPage, int totalItemCount)
            : base(htmlHelper, pageSize, currentPage, totalItemCount)
        {
            this.htmlHelper = htmlHelper;
        }

        public Pager<TModel> Options(Action<PagerOptionsBuilder<TModel>> buildOptions)
        {
            buildOptions(new PagerOptionsBuilder<TModel>(pagerOptions, htmlHelper));
            return this;
        }
    }

PagerOptions.cs

using System.Web.Mvc.Ajax;
using System.Web.Routing;

namespace MvcPaging
{
    public class PagerOptions
    {
        public PagerOptions()
        {
            RouteValues = new RouteValueDictionary();
            DisplayTemplate = Defaults.DisplayTemplate;
            MaxNrOfPages = Defaults.MaxNrOfPages;
            AlwaysAddFirstPageNumber = Defaults.AlwaysAddFirstPageNumber;
            PageRouteValueKey = Defaults.DefaultPageRouteValueKey;
            PreviousPageText = DefaultDefaults.PreviousPageText;
            PreviousPageTitle = DefaultDefaults.PreviousPageTitle;
            NextPageText = DefaultDefaults.NextPageText;
            NextPageTitle = DefaultDefaults.NextPageTitle;
            FirstPageText = DefaultDefaults.FirstPageText;
            FirstPageTitle = DefaultDefaults.FirstPageTitle;
            LastPageText = DefaultDefaults.LastPageText;
            LastPageTitle = DefaultDefaults.LastPageTitle;
            DisplayFirstPage = DefaultDefaults.DisplayFirstPage;
            DisplayLastPage = DefaultDefaults.DisplayLastPage;
            UseItemCountAsPageCount = DefaultDefaults.UseItemCountAsPageCount;
            HidePreviousAndNextPage = DefaultDefaults.HidePreviousAndNextPage;
        }

        public RouteValueDictionary RouteValues { get; internal set; }

        public string DisplayTemplate { get; internal set; }

        public int MaxNrOfPages { get; internal set; }

        public AjaxOptions AjaxOptions { get; internal set; }

        public bool AlwaysAddFirstPageNumber { get; internal set; }

        public string Action { get; internal set; }

        public string PageRouteValueKey { get; set; }

        public string PreviousPageText { get; set; }

        public string PreviousPageTitle { get; set; }

        public string NextPageText { get; set; }

        public string NextPageTitle { get; set; }

        public string FirstPageText { get; set; }

        public string FirstPageTitle { get; set; }

        public string LastPageText { get; set; }

        public string LastPageTitle { get; set; }

        public bool DisplayFirstAndLastPage
        {
            get { return DisplayFirstPage && DisplayLastPage; }
        }

        public bool DisplayFirstPage { get; set; }
        public bool DisplayLastPage { get; set; }

        public bool HidePreviousAndNextPage { get; internal set; }

        public bool UseItemCountAsPageCount { get; internal set; }

        public static class DefaultDefaults
        {
            public const int MaxNrOfPages = 10;
            public const string DisplayTemplate = null;
            public const bool AlwaysAddFirstPageNumber = false;
            public const string DefaultPageRouteValueKey = "page";
            public const string PreviousPageText = "«";
            public const string PreviousPageTitle = "Previous page";
            public const string NextPageText = "»";
            public const string NextPageTitle = "Next page";
            public const string FirstPageText = "<";
            public const string FirstPageTitle = "First page";
            public const string LastPageText = ">";
            public const string LastPageTitle = "Last page";
            public const bool DisplayFirstPage = false;
            public const bool DisplayLastPage = false;
            public const bool UseItemCountAsPageCount = false;
            public static bool HidePreviousAndNextPage = false;
        }

        /// <summary>
        /// 静态Defaults类允许您为整个应用程序设置Pager默认值。
        ///在应用程序启动时设置值。
        /// </summary>
        public static class Defaults
        {
            public static int MaxNrOfPages = DefaultDefaults.MaxNrOfPages;
            public static string DisplayTemplate = DefaultDefaults.DisplayTemplate;
            public static bool AlwaysAddFirstPageNumber = DefaultDefaults.AlwaysAddFirstPageNumber;
            public static string DefaultPageRouteValueKey = DefaultDefaults.DefaultPageRouteValueKey;
            public static string PreviousPageText = DefaultDefaults.PreviousPageText;
            public static string PreviousPageTitle = DefaultDefaults.PreviousPageTitle;
            public static string NextPageText = DefaultDefaults.NextPageText;
            public static string NextPageTitle = DefaultDefaults.NextPageTitle;
            public static string FirstPageText = DefaultDefaults.FirstPageText;
            public static string FirstPageTitle = DefaultDefaults.FirstPageTitle;
            public static string LastPageText = DefaultDefaults.LastPageText;
            public static string LastPageTitle = DefaultDefaults.LastPageTitle;
            public static bool DisplayFirstPage = DefaultDefaults.DisplayFirstPage;
            public static bool DisplayLastPage = DefaultDefaults.DisplayLastPage;
            public static bool UseItemCountAsPageCount = DefaultDefaults.UseItemCountAsPageCount;

            public static void Reset()
            {
                MaxNrOfPages = DefaultDefaults.MaxNrOfPages;
                DisplayTemplate = DefaultDefaults.DisplayTemplate;
                AlwaysAddFirstPageNumber = DefaultDefaults.AlwaysAddFirstPageNumber;
                DefaultPageRouteValueKey = DefaultDefaults.DefaultPageRouteValueKey;
                PreviousPageText = DefaultDefaults.PreviousPageText;
                PreviousPageTitle = DefaultDefaults.PreviousPageTitle;
                NextPageText = DefaultDefaults.NextPageText;
                NextPageTitle = DefaultDefaults.NextPageTitle;
                FirstPageText = DefaultDefaults.FirstPageText;
                FirstPageTitle = DefaultDefaults.FirstPageTitle;
                LastPageText = DefaultDefaults.LastPageText;
                LastPageTitle = DefaultDefaults.LastPageTitle;
                DisplayFirstPage = DefaultDefaults.DisplayFirstPage;
                DisplayLastPage = DefaultDefaults.DisplayLastPage;
                UseItemCountAsPageCount = DefaultDefaults.UseItemCountAsPageCount;
            }
        }
    }
}

PagerOptionsBuilder.cs类

using System;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Routing;

namespace MvcPaging
{
    /// <summary>
    ///     分页选项构建器类。 启用流畅的接口,为分页添加选项。
    /// </summary>
    public class PagerOptionsBuilder
    {
        protected PagerOptions pagerOptions;

        public PagerOptionsBuilder(PagerOptions pagerOptions)
        {
            this.pagerOptions = pagerOptions;
        }

        /// <summary>
        ///     设置分页链接的动作名称。 请注意,我们总是使用当前的控制器。
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public PagerOptionsBuilder Action(string action)
        {
            if (action != null)
            {
                if (pagerOptions.RouteValues.ContainsKey("action"))
                {
                    throw new ArgumentException("The valuesDictionary already contains an action.", "action");
                }
                pagerOptions.RouteValues.Add("action", action);
                pagerOptions.Action = action;
            }
            return this;
        }

        /// <summary>
        ///     为分页链接添加自定义路由值参数。
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public PagerOptionsBuilder AddRouteValue(string name, object value)
        {
            pagerOptions.RouteValues[name] = value;
            return this;
        }

        /// <summary>
        ///    设置上一页导航的文本
        /// </summary>
        /// <param name="previousPageText"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetPreviousPageText(string previousPageText)
        {
            pagerOptions.PreviousPageText = previousPageText;
            return this;
        }

        /// <summary>
        ///   设置前一页导航的标题
        /// </summary>
        /// <param name="previousPageTitle"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetPreviousPageTitle(string previousPageTitle)
        {
            pagerOptions.PreviousPageTitle = previousPageTitle;
            return this;
        }

        /// <summary>
        ///    设置下一页导航的文本
        /// </summary>
        /// <param name="nextPageText"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetNextPageText(string nextPageText)
        {
            pagerOptions.NextPageText = nextPageText;
            return this;
        }

        /// <summary>
        ///  设置下一页导航的标题
        /// </summary>
        /// <param name="nextPageTitle"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetNextPageTitle(string nextPageTitle)
        {
            pagerOptions.NextPageTitle = nextPageTitle;
            return this;
        }

        /// <summary>
        ///   设置第一页导航的文本
        /// </summary>
        /// <param name="firstPageText"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetFirstPageText(string firstPageText)
        {
            pagerOptions.FirstPageText = firstPageText;
            return this;
        }

        /// <summary>
        ///   设置第一页导航的标题
        /// </summary>
        /// <param name="firstPageTitle"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetFirstPageTitle(string firstPageTitle)
        {
            pagerOptions.FirstPageTitle = firstPageTitle;
            return this;
        }

        /// <summary>
        ///    设置最后一页导航的文本
        /// </summary>
        /// <param name="lastPageText"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetLastPageText(string lastPageText)
        {
            pagerOptions.LastPageText = lastPageText;
            return this;
        }

        /// <summary>
        ///    设置最后一页导航的标题
        /// </summary>
        /// <param name="lastPageTitle"></param>
        /// <returns></returns>
        public PagerOptionsBuilder SetLastPageTitle(string lastPageTitle)
        {
            pagerOptions.LastPageTitle = lastPageTitle;
            return this;
        }

        /// <summary>
        ///    显示第一个和最后一个导航页面
        /// </summary>
        /// <returns></returns>
        public PagerOptionsBuilder DisplayFirstAndLastPage()
        {
            pagerOptions.DisplayFirstPage = true;
            pagerOptions.DisplayLastPage = true;
            return this;
        }

        /// <summary>
        ///     Displays the first navigation page but not the last.
        /// </summary>
        /// <returns></returns>
        public PagerOptionsBuilder DisplayFirstPage()
        {
            pagerOptions.DisplayFirstPage = true;
            return this;
        }

        /// <summary>
        ///  显示最后一个导航页,但不显示第一个
        /// </summary>
        /// <returns></returns>
        public PagerOptionsBuilder DisplayLastPage()
        {
            pagerOptions.DisplayLastPage = true;
            return this;
        }

        public PagerOptionsBuilder HidePreviousAndNextPage()
        {
            pagerOptions.HidePreviousAndNextPage = true;
            return this;
        }

        /// <summary>
        ///   设置分页链接的自定义路由值参数
        /// </summary>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public PagerOptionsBuilder RouteValues(object routeValues)
        {
            RouteValues(new RouteValueDictionary(routeValues));
            return this;
        }

        /// <summary>
        ///    设置分页链接的自定义路由值参数
        /// </summary>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public PagerOptionsBuilder RouteValues(RouteValueDictionary routeValues)
        {
            if (routeValues == null)
            {
                throw new ArgumentException("routeValues may not be null", "routeValues");
            }
            pagerOptions.RouteValues = routeValues;
            if (!string.IsNullOrWhiteSpace(pagerOptions.Action) && !pagerOptions.RouteValues.ContainsKey("action"))
            {
                pagerOptions.RouteValues.Add("action", pagerOptions.Action);
            }
            return this;
        }

        /// <summary>
        ///    设置要用于呈现的DisplayTemplate视图的名称
        /// </summary>
        /// <param name="displayTemplate"></param>
        /// <remarks>该视图必须具有IEnumerable<PaginationModel>的模型。</remarks>
        /// <returns></returns>
        public PagerOptionsBuilder DisplayTemplate(string displayTemplate)
        {
            pagerOptions.DisplayTemplate = displayTemplate;
            return this;
        }

        /// <summary>
        ///  设置要显示的最大页数。 默认值为10
        /// </summary>
        /// <param name="maxNrOfPages"></param>
        /// <returns></returns>
        public PagerOptionsBuilder MaxNrOfPages(int maxNrOfPages)
        {
            pagerOptions.MaxNrOfPages = maxNrOfPages;
            return this;
        }

        /// <summary>
        ///   始终将页码添加到生成的第一页链接。
        /// </summary>
        /// <remarks>
        ///     默认情况下,我们不会添加第1页的页码,因为它会导致(网址形式不同内容相同而造成的内容重复问题)链接。
        ///    使用此选项来覆盖此行为。
        /// </remarks>
        /// <returns></returns>
        public PagerOptionsBuilder AlwaysAddFirstPageNumber()
        {
            pagerOptions.AlwaysAddFirstPageNumber = true;
            return this;
        }

        /// <summary>
        ///  设置分页链接的page routeValue键
        /// </summary>
        /// <param name="pageRouteValueKey"></param>
        /// <returns></returns>
        public PagerOptionsBuilder PageRouteValueKey(string pageRouteValueKey)
        {
            if (pageRouteValueKey == null)
            {
                throw new ArgumentException("pageRouteValueKey may not be null", "pageRouteValueKey");
            }
            pagerOptions.PageRouteValueKey = pageRouteValueKey;
            return this;
        }

        /// <summary>
        /// 表示总计数表示总页数。 此选项适用于某些后端不返回总项目数量但有页数的情况。
        /// </summary>
        /// <returns></returns>
        public PagerOptionsBuilder UseItemCountAsPageCount()
        {
            pagerOptions.UseItemCountAsPageCount = true;
            return this;
        }

        /// <summary>
        /// 设置AjaxOptions
        /// </summary>
        /// <param name="ajaxOptions"></param>
        /// <returns></returns>
        internal PagerOptionsBuilder AjaxOptions(AjaxOptions ajaxOptions)
        {
            pagerOptions.AjaxOptions = ajaxOptions;
            return this;
        }
    }

    /// <summary>
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public class PagerOptionsBuilder<TModel> : PagerOptionsBuilder
    {
        private readonly HtmlHelper<TModel> htmlHelper;

        public PagerOptionsBuilder(PagerOptions pagerOptions, HtmlHelper<TModel> htmlHelper)
            : base(pagerOptions)
        {
            this.htmlHelper = htmlHelper;
        }

        /// <summary>
        ///   根据当前模型添加强类型路由值参数
        /// </summary>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="expression"></param>
        /// <example>AddRouteValueFor(m => m.SearchQuery)</example>
        /// <returns></returns>
        public PagerOptionsBuilder<TModel> AddRouteValueFor<TProperty>(Expression<Func<TModel, TProperty>> expression)
        {
            string name = ExpressionHelper.GetExpressionText(expression);
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            AddRouteValue(name, metadata.Model);

            return this;
        }

        /// <summary>
        ///  设置分页链接的动作名称。 请注意,我们总是使用当前的控制器。
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> Action(string action)
        {
            base.Action(action);
            return this;
        }

        /// <summary>
        ///  为分页链接添加自定义路由值参数。
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> AddRouteValue(string name, object value)
        {
            base.AddRouteValue(name, value);
            return this;
        }

        /// <summary>
        ///  设置分页链接的自定义路由值参数。
        /// </summary>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> RouteValues(object routeValues)
        {
            base.RouteValues(routeValues);
            return this;
        }

        /// <summary>
        ///  设置分页链接的自定义路由值参数
        /// </summary>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> RouteValues(RouteValueDictionary routeValues)
        {
            base.RouteValues(routeValues);
            return this;
        }

        /// <summary>
        ///   设置要用于呈现的DisplayTemplate视图的名称
        /// </summary>
        /// <param name="displayTemplate"></param>
        /// <remarks>该视图必须具有IEnumerable<PaginationModel>的模型</remarks>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> DisplayTemplate(string displayTemplate)
        {
            base.DisplayTemplate(displayTemplate);
            return this;
        }

        /// <summary>
        /// 设置要显示的最大页数。 默认值为10。
        /// </summary>
        /// <param name="maxNrOfPages"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> MaxNrOfPages(int maxNrOfPages)
        {
            base.MaxNrOfPages(maxNrOfPages);
            return this;
        }

        /// <summary>
        ///  始终将页码添加到生成的第一页链接。
        /// </summary>
        /// <remarks>
        ///  默认情况下,我们不会添加第1页的页码,因为它会导致规范链接。
        ///  使用此选项来覆盖此行为
        /// </remarks>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> AlwaysAddFirstPageNumber()
        {
            base.AlwaysAddFirstPageNumber();
            return this;
        }

        /// <summary>
        ///  设置分页链接的page routeValue键
        /// </summary>
        /// <param name="pageRouteValueKey"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> PageRouteValueKey(string pageRouteValueKey)
        {
            if (pageRouteValueKey == null)
            {
                throw new ArgumentException("pageRouteValueKey may not be null", "pageRouteValueKey");
            }
            pagerOptions.PageRouteValueKey = pageRouteValueKey;
            return this;
        }

        /// <summary>
        ///     Set the text for previous page navigation.
        /// </summary>
        /// <param name="previousPageText"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetPreviousPageText(string previousPageText)
        {
            base.SetPreviousPageText(previousPageText);
            return this;
        }

        /// <summary>
        /// 设置前一页导航的标题
        /// </summary>
        /// <param name="previousPageTitle"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetPreviousPageTitle(string previousPageTitle)
        {
            base.SetPreviousPageTitle(previousPageTitle);
            return this;
        }

        /// <summary>
        ///  设置下一页导航的文本
        /// </summary>
        /// <param name="nextPageText"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetNextPageText(string nextPageText)
        {
            base.SetNextPageText(nextPageText);
            return this;
        }

        /// <summary>
        /// 设置下一页导航的标题
        /// </summary>
        /// <param name="nextPageTitle"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetNextPageTitle(string nextPageTitle)
        {
            base.SetNextPageTitle(nextPageTitle);
            return this;
        }

        /// <summary>
        ///  设置第一页导航的文本
        /// </summary>
        /// <param name="firstPageText"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetFirstPageText(string firstPageText)
        {
            base.SetFirstPageText(firstPageText);
            return this;
        }

        /// <summary>
        /// 设置第一页导航的标题
        /// </summary>
        /// <param name="firstPageTitle"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetFirstPageTitle(string firstPageTitle)
        {
            base.SetFirstPageTitle(firstPageTitle);
            return this;
        }

        /// <summary>
        ///  设置最后一页导航的文本
        /// </summary>
        /// <param name="lastPageText"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetLastPageText(string lastPageText)
        {
            base.SetLastPageText(lastPageText);
            return this;
        }

        /// <summary>
        ///  设置最后一页导航的标题
        /// </summary>
        /// <param name="lastPageTitle"></param>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> SetLastPageTitle(string lastPageTitle)
        {
            base.SetLastPageTitle(lastPageTitle);
            return this;
        }

        /// <summary>
        ///   显示第一个和最后一个导航页
        /// </summary>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> DisplayFirstAndLastPage()
        {
            base.DisplayFirstAndLastPage();
            return this;
        }

        /// <summary>
        ///    表示总计数表示总页数。 此选项适用于某些后端不返回总项目数量但有页数的情况
        /// </summary>
        /// <returns></returns>
        public new PagerOptionsBuilder<TModel> UseItemCountAsPageCount()
        {
            base.UseItemCountAsPageCount();
            return this;
        }
    }
}

PaginationModel.cs类:

using System.Collections.Generic;
using System.Web.Mvc.Ajax;

namespace MvcPaging
{
    public class PaginationModel
    {
        public PaginationModel()
        {
            PaginationLinks = new List<PaginationLink>();
            AjaxOptions = null;
            Options = null;
        }

        public int PageSize { get; internal set; }

        public int CurrentPage { get; internal set; }

        public int PageCount { get; internal set; }

        public int TotalItemCount { get; internal set; }

        public IList<PaginationLink> PaginationLinks { get; private set; }

        public AjaxOptions AjaxOptions { get; internal set; }

        public PagerOptions Options { get; internal set; }
    }

    public class PaginationLink
    {
        public bool Active { get; set; }

        public bool IsCurrent { get; set; }

        public int? PageIndex { get; set; }

        public string DisplayText { get; set; }

        public string DisplayTitle { get; set; }

        public string Url { get; set; }

        public bool IsSpacer { get; set; }
    }
}

PagingExtensions.cs

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcPaging
{
    public static class PagingExtensions
    {
        #region HtmlHelper extensions

        public static Pager Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount)
        {
            return new Pager(htmlHelper, pageSize, currentPage, totalItemCount);
        }

        public static Pager Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount,
            AjaxOptions ajaxOptions)
        {
            return new Pager(htmlHelper, pageSize, currentPage, totalItemCount).Options(o => o.AjaxOptions(ajaxOptions));
        }

        public static Pager<TModel> Pager<TModel>(this HtmlHelper<TModel> htmlHelper, int pageSize, int currentPage,
            int totalItemCount)
        {
            return new Pager<TModel>(htmlHelper, pageSize, currentPage, totalItemCount);
        }

        public static Pager<TModel> Pager<TModel>(this HtmlHelper<TModel> htmlHelper, int pageSize, int currentPage,
            int totalItemCount, AjaxOptions ajaxOptions)
        {
            return
                new Pager<TModel>(htmlHelper, pageSize, currentPage, totalItemCount).Options(
                    o => o.AjaxOptions(ajaxOptions));
        }

        #endregion

        #region IQueryable<T> extensions

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize,
            int? totalCount = null)
        {
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        #endregion

        #region IEnumerable<T> extensions

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int pageIndex, int pageSize,
            int? totalCount = null)
        {
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        #endregion
    }
}

RouteValueDictionaryExtensions.cs

using System.Collections;
using System.Web.Routing;

namespace MvcPaging
{
    public static class RouteValueDictionaryExtensions
    {
        /// <summary>
        ///   修复包含数组的RouteValueDictionary
        ///   Source: http://stackoverflow.com/a/5208050/691965
        /// </summary>
        /// <param name="routes"></param>
        /// <returns></returns>
        public static RouteValueDictionary FixListRouteDataValues(this RouteValueDictionary routes)
        {
            var newRv = new RouteValueDictionary();
            foreach (string key in routes.Keys)
            {
                object value = routes[key];
                if (value is IEnumerable && !(value is string))
                {
                    int index = 0;
                    foreach (object val in (IEnumerable) value)
                    {
                        newRv.Add(string.Format("{0}[{1}]", key, index), val);
                        index++;
                    }
                }
                else
                {
                    newRv.Add(key, value);
                }
            }
            return newRv;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值