ASP.NET分页

效果 ASP.NET分页

前台页面代码(MyPager.ascx):

<asp:PlaceHolder ID="holder" runat="server"></asp:PlaceHolder>

后台页面代码(MyPager.ascx.cs):

public partial class MyPager : System.Web.UI.UserControl
    {
        private int pageSize;      //默认每页多少条记录
        private int totalCount = 0;     //默认总记录数
        private int totalPage;          //总页数
        private int currentPage = 1;    //默认当前是第几页
        private int offsetCount = 4;    //默认偏移量

        private string url;

        /// <summary>
        /// 总记录数
        /// </summary>
        public int TotalCount
        {
            get { return totalCount; }
            set { totalCount = value; }
        }

        /// <summary>
        /// 页容量
        /// </summary>
        public int PageSize
        {
            get { return pageSize; }
            set { pageSize = value; }
        }

        /// <summary>
        /// 当前页
        /// </summary>
        public int CurrentPage
        {
            get { return currentPage; }
            set { currentPage = value; }
        }

        /// <summary>
        /// div的样式
        /// </summary>
        public string CssClass
        {
            get;
            set;
        }

        /// <summary>
        /// 当前页显示的样式
        /// </summary>
        public string CurrentPageCssClass
        {
            get;
            set;
        }

        private bool showSinglePage = false;
        /// <summary>
        /// 如果总页数只有1, 是否显示(默认不显示)
        /// </summary>
        public bool ShowSinglePage
        {
            get { return showSinglePage; }
            set { showSinglePage = value; }
        }

        /// <summary>
        /// 重载OnInit事件, 介样, 内容页面(Page_Load)就可以直接得到CurrentPage和PageSize参数
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            int tmpPage = 1;

            //获取当前页
            if (int.TryParse(Request.Params.Get("page"), out tmpPage) && tmpPage > 0)
            {
                currentPage = tmpPage;
            }

            //获取pagesize
            GetPageSize();

            //生成链接
            GetUrl();

            base.OnInit(e);
        }

        /// <summary>
        /// 由于页面的执行顺序是Page_Load, Control_Event, Page_PreRender, 
        /// 所以如果将 CreatePage()方法放在Page_Load中, 那么分页控件将无法准确执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_PreRender(object sender, EventArgs e)
        {
            holder.Controls.Clear();

            var wrapper = new HtmlGenericControl("div");
            wrapper.Attributes["id"] = ClientID;
            wrapper.Attributes["class"] = this.CssClass;

            //创建链接, 并附加到wrapper中
            this.CreatePage(wrapper);

            //如果有子元素, 那么将其附加到placeholder中
            if (wrapper.Controls.Count > 0)
                holder.Controls.Add(wrapper);

            //base.OnPreRender(e);
        }

        /// <summary>
        /// 获取pageSize
        ///  1, 试图从url中得到pagesize参数
        ///  2, 如果1不行, 那么试图从cookie中得到该参数
        ///  3, 如果2不行, 那么就会从config中得到该值
        /// </summary>
        /// <param name="tmpPagesize"></param>
        /// <returns></returns>
        private void GetPageSize()
        {
            int tmpPagesize = 10;

            if (int.TryParse(Request.QueryString.Get("pagesize"), out tmpPagesize) && tmpPagesize > 0)
            {
                pageSize = tmpPagesize;

                //如果检测到cookie中有pagesize, 那么就更新
                var rqSize = Request.Cookies.Get("pagesize");
                if (rqSize == null)
                {
                    var cookie = new System.Web.HttpCookie("pagesize", pageSize.ToString());
                    Response.Cookies.Add(cookie);
                }
                else if (rqSize != null && rqSize.Value != pageSize.ToString())
                {
                    rqSize.Value = pageSize.ToString();
                    Response.SetCookie(rqSize);
                }

                return;
            }
            else if (pageSize <= 0)
            {
                pageSize = PubUtility.WebParameter.Parm_GVlines;
            }

        }

        /// <summary>
        /// 得到当前页面的所有参数, 并且重组成一个去掉page参数的url
        /// </summary>
        private void GetUrl()
        {
            
            string url = Request.Path+"?";

            if (Request.QueryString.Count < 1)
            {
                this.url = url;
                return;
            }

            foreach (string k in Request.QueryString.Keys)
            {
                //去除url中的page参数
                if (k == "page" || string.IsNullOrWhiteSpace(k)) continue;
                url += k + "=" + Server.UrlEncode(Request.QueryString[k]) + "&";
            }

            this.url = url;
        }

        /// <summary>
        /// 生成翻页的链接
        /// </summary>
        private void CreatePage(HtmlGenericControl father)
        {
            var ctrl = father.Controls;

            totalPage = (int)Math.Ceiling(TotalCount / (PageSize + 0.0));// +TotalCount % PageSize;

            //如果总页数只有1页, 并且showSinglePage==false, 那么啥也不做
            if (!showSinglePage && totalPage == 1) return;

            //过滤掉不正常的CurrentPage, 比如当前页比总页数还要大, 或者是负数等等
            //当然这里过滤显然已经晚了, 因为此时是在页面预呈现的时候生成的html, 在这之前(没有经过验证的)CurrentPage可能已经被利用了
            currentPage = Math.Min(currentPage, totalPage);
            currentPage = Math.Max(currentPage, 1);

            //左边/右边偏移量
            //正常情况下 翻页数应当从offsetLeft开始, 到offsetRight结束
            //但是还需要考虑些特殊情况, 比如左偏移小于1, 或者右偏移大于总页数
            int offsetLeft = Math.Max((currentPage - offsetCount), 1);
            int offsetRight = Math.Min((currentPage + offsetCount), totalPage);

            //使分页更加整齐
            if ((offsetRight - offsetLeft) <= 2 * offsetCount)
            {
                offsetRight = Math.Min((2 * offsetCount + offsetLeft), totalPage);
                offsetLeft = Math.Max((offsetRight - 2 * offsetCount), 1);
            }

            //又使分页更加整齐了, 这句代码完全可以干掉
            if (offsetLeft == 1)
                offsetRight = Math.Min((offsetRight + 1), totalPage);

            //当当前页大于1的时候显示上一页
            if (currentPage > 1) ctrl.Add(SetHyperLink(currentPage - 1, "上一页"));

            //当左偏移量大于1的时候显示第一页
            if (offsetLeft > 1) ctrl.Add(SetHyperLink(1, "1"));
            if (offsetLeft > 2) ctrl.Add(SetSpan());

            for (var i = offsetLeft; i <= offsetRight; i++)
            {
                if (i == currentPage)
                {
                    ctrl.Add(SetHyperLink(null, i.ToString(), CurrentPageCssClass));
                    continue;
                }
                ctrl.Add(SetHyperLink(i, i.ToString()));
            }

            //当右偏移量比总页数小的时候显示最后一页
            if (offsetRight < totalPage - 1) ctrl.Add(SetSpan());
            if (offsetRight < totalPage) ctrl.Add(SetHyperLink(totalPage, totalPage.ToString()));

            //下一页
            if (currentPage < totalPage) ctrl.Add(SetHyperLink(currentPage + 1, "下一页"));

        }

        private HtmlAnchor SetHyperLink(int page)
        {
            return this.SetHyperLink(page, page.ToString());
        }

        private HtmlAnchor SetHyperLink(int page, string name)
        {
            return this.SetHyperLink(page, name, null);
        }

        private HtmlAnchor SetHyperLink(int? page, string name, string className)
        {
            string url = page == null
                ? "javascript:void(0);"
                : (this.url + "page=" + page);

            HtmlAnchor a = new HtmlAnchor();
            a.InnerText = name;
            a.HRef = url;

            if (!string.IsNullOrEmpty(className))
                a.Attributes["class"] = className;

            return a;
        }

        private HtmlGenericControl SetSpan(string innerHTML = "...")
        {
            var span = new HtmlGenericControl("span");
            span.InnerHtml = innerHTML;
            return span;
        }

    }