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; } }