Go homepage(回首页) Upload pictures (上传图片) Write articles (发文字帖)
The author:(作者)归海一刀published in(发表于) 2014/1/30 0:53:16 Asp.Net,可自定义分页用户控件_[Asp.Net教程]
借助 Asp.Net 提供的数据绑定控件,我们无需太多的代码,甚至不需要代码,只要在 VS2005 中拖拽几下控件,进行一些属性的设置,便可以实现在Asp时代需要做大量工作才能够实现的分页功能。但在实际的应用中,尤其是在Web站点程序中,我们经常需要更加丰富的用户界面,而类似DataList或者 GridView 这样的数据控件往往不能或者很难满足我们的要求。此时,我们常常求助于 Repeater 控件,这样我们依旧会面临分页及其显示的问题。
本文不是讲述如何进行数据库分页,而将注意力集中在如何实现可定制地 获取页码、获取路径、显示分页链接,并且通过构建一个用户控件来实现代码重用上。这个用户控件我自己正在使用,如果你是一个初学者,你可以借鉴一下我的实现方式;如果你已经是一位高手,不妨提出设计的不足和改进意见。
为了能迅速提起大家的兴趣,可以先点击这个链接,看看实际的效果:
http://www.tracefact.net/Demo/Pager/Default.aspx
想一想如果你在设计一个可重用的分页用户控件,你面临的问题是什么?每个人获取页码的方式都不同,例如,你的站点URL可能是类似这样的 Default.aspx?page=1 ,而另外一个站点的URL 是这样的 Default.aspx?p=1。更有一些可能根本不使用 QueryString 来获取页码,它们的URL可能是这样的 Default-1.aspx、Default-2.aspx 等等。获取页码的方式不同,根据页码产生链接地址的方法自然也不相同。按照封装变化的思想,我们应该将这变化的部分取出来,建一个 IUrlManager 接口:
public interface IUrlManager{ int GetCurrentPageIndex(); // 获取 当前页面 的页码 string GetPageUrl(int pageIndex); // 根据 页码 获取页面路径 }
现在 所有获取页码 及 根据页码获取路径 的逻辑都可以放在实现了这个接口的类中。如果你想使用这个控件,你需要提供一个实现了IUrlManger接口的类。为了使控件立即可用,我在这里提供了一个默认实现,我管它叫做 DefaultUrlManger。它通过Request.QueryString获取页码,并默认以"Page"作为参数。
public class DefaultUrlManager : IUrlManager { private HttpContext context; private Regex reg; private string queryParam; public DefaultUrlManager(string queryParam) { this.queryParam = queryParam; context = HttpContext.Current; string pattern = @"(?[?&]" + queryParam + @"=)[^&]+"; reg = new Regex(pattern, RegexOptions.IgnoreCase); } public DefaultUrlManager() : this("Page") { } public string GetPageUrl(int pageIndex) { string pageUrl = context.Request.RawUrl; // 如果找到匹配,也就是URL中含有类似 ?page=3 或者 &page=4 这样的字符串 // 则对后面的数值进行替换 if (reg.IsMatch(pageUrl)) { pageUrl = reg.Replace(pageUrl, "{r1}" + pageIndex.ToString()); } else { string queryString = context.Request.Url.Query; if (string.IsNullOrEmpty(queryString)) pageUrl += "?" + queryParam + "=" + pageIndex.ToString(); else pageUrl += "&" + queryParam + "=" + pageIndex.ToString(); } return pageUrl; } public int GetCurrentPageIndex() { string queryIndex = context.Request.QueryString[queryParam]; if (string.IsNullOrEmpty(queryIndex)) return 1; else { int pageIndex; try { pageIndex = Math.Abs(int.Parse(queryIndex)); } catch { pageIndex = 1; } return pageIndex; } }}
由于我们的链接是动态生成的,所以我们大部分的代码都会存在于 Pager.ascx.cs 中,在Pager.ascx 文件中,我们只提供一个装链接的容器:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Pager.ascx.cs" Inherits="CustomPager" %>
我们对于页面的显示的主要实现都放置在了这个文件中,我在文件中做了大量注释,这里就不再文字描述了:
using System;// ... 略public partial class CustomPager : System.Web.UI.UserControl{ private int pageSize = 10; // 分页大小 private int recordCount; // 记录总数 private int pageCount; // 总页数 private int currentPage; // 当前页的页码 private int previousPageCount = 5; // 当前页之前可以显示的最多条目数,大于此条目的将被隐藏 private int afterPageCount = 4; // 当前页之后可以显示的最多条目数,大于此条目的将被隐藏 private bool showPrevious = false; // 是否显示 上一页、第一页 的链接 private bool showNext = false; // 是否显示 下一页、最末页 的链接 private int startPage; // 显示的第一页 的 页码 private int endPage; // 显示的最末页 的 页码 private IUrlManager urlManager; // 设置接口 public int RecordCount { get { return recordCount; } set { recordCount = value; } } public int PageSize { get { return pageSize; } set { pageSize = value; } } public int PreviousPageCount { get { return previousPageCount; } set { previousPageCount = value; } } public int AfterPageCount { get { return afterPageCount; } set { afterPageCount = value; } } public IUrlManager UrlManager { get { return urlManager; } set { urlManager = value; } } // 设置 pnPager Div 的 CssClass 属性,通过它来为控件定义样式 public string CssClass { set { pnPager.CssClass = value; } get { return pnPager.CssClass; } } private void RenderPager() { if (urlManager == null) { urlManager = new DefaultUrlManager(); } // 获取页数 double recordCount2 = Convert.ToDouble(recordCount); double pageSize2 = Convert.ToDouble(pageSize); pageCount = Convert.ToInt32(Math.Ceiling(recordCount2 / pageSize2)); // 获取当前页 currentPage = urlManager.GetCurrentPageIndex(); if (currentPage < 0) currentPage = 1; else if (currentPage > pageCount) currentPage = pageCount; SetStartPage(); SetEndPage(); HyperLink link; // 循环打印链接 for (int i = startPage; i <= endPage; i++) { if (showPrevious) // 如果需要显示前一页、第一页链接 AddPreviousLink(urlManager); link = new HyperLink(); if (i == currentPage) link.CssClass = "CurrentPage"; link.Text = i.ToString(); link.NavigateUrl = urlManager.GetPageUrl(i); pnPager.Controls.Add(link); if (i == endPage && showNext) // 如果需要显示 下一页、最末页 链接 AddNextLink(urlManager); } Label lbCount = new Label(); lbCount.Text = String.Format(" ( 第{0}页/共{1}页 )", currentPage, pageCount); pnPager.Controls.Add(lbCount); } // 添加“第一页”,“上一页”的连接 private void AddPreviousLink(IUrlManager urlManager) { HyperLink first = new HyperLink(); first.CssClass = "PagerIcon"; first.Text = "<<"; first.ToolTip = "第一页"; first.NavigateUrl = urlManager.GetPageUrl(1); pnPager.Controls.Add(first); HyperLink previous = new HyperLink(); previous.CssClass = "PagerIcon"; previous.Text = "<"; previous.ToolTip = "上一页"; previous.NavigateUrl = urlManager.GetPageUrl(currentPage - 1); pnPager.Controls.Add(previous); showPrevious = false; // 只显示一次 } // 添加 “下一页”、“最末页” 的链接 private void AddNextLink(IUrlManager urlManager) { HyperLink next = new HyperLink(); next.CssClass = "PagerIcon"; next.Text = ">"; next.ToolTip = "下一页"; next.NavigateUrl = urlManager.GetPageUrl(currentPage + 1); pnPager.Controls.Add(next); HyperLink last = new HyperLink(); last.CssClass = "PagerIcon"; last.Text = ">>"; last.ToolTip = "最末页"; last.NavigateUrl = urlManager.GetPageUrl(pageCount); pnPager.Controls.Add(last); showNext = false; // 可有可无,程序会跳出循环 } // 根据当前页,当前页之前可以显示的页数,算得从第几页开始进行显示 private void SetStartPage() { // 如果当前页小于 它前面所可以显示的条目数,那么显示第一页就是实际的第一页 if (currentPage <= previousPageCount) { startPage = 1; } else // 这种情况下 currentPage 前面总是能显示完,要根据后面的长短确定是不是前面应该多显示 { if(currentPage > previousPageCount+1) showPrevious = true; int linkLength = (pageCount - currentPage + 1) + previousPageCount; int startPage = currentPage - previousPageCount; while (linkLength < previousPageCount + afterPageCount + 1 && startPage > 1) { linkLength++; startPage--; } this.startPage = startPage; } } // 根据CurrentPage、总页数、当前页之后长度 算得显示的最末页是 第几页 private void SetEndPage() { // 如果当前页加上它之后可以显示的页数 大于 总页数,那么显示的最末页就是实际的最末页 if (currentPage + afterPageCount >= pageCount) { endPage = pageCount; } else // 这种情况下 currentPage后面的总是可以显示完,要根据前面的长短确定是不是后面应该多显示 { int linkLength = (currentPage - startPage + 1) + afterPageCount; int endPage = currentPage + afterPageCount; while (linkLength < previousPageCount + afterPageCount + 1 && endPage < pageCount) { linkLength++; endPage++; } if (endPage < pageCount) showNext = true; this.endPage = endPage; } } protected void Page_Load(object sender, EventArgs e) { RenderPager(); }}
控件没有提供任何的样式控制,对于样式,你唯一能做的就是通过它的CssClass属性来设置由Panel控件生成的Div的Class,然后利用这个Class编写样式表来控制显示。如果有必要,你还可以通过利用PagerIcon这个Css类来控制“上一页”、“下一页”、“第一页”、“最末页”的显示;通过 CurrentPage 这个Css类来控制 当前页 的显示。由此,在所有使用这个控件的页面,你都应该包含有控制控件样式的样式表。
这里,我提供了一个默认的实现(在你不设置控件的CssClass属性的时候,默认为Pager):
.Pager a{ display:block; border:1px solid #ccc; float:left; padding:4px 5px; text-decoration:none; text-align:center; margin:0 1px;}.Pager a.CurrentPage{ background:#999; color:#eee;}.Pager span{ position:relative; top:6px;}
好了,现在一切都OK了,让我们看看控件如何使用。我们以一种最简单的方式开始,再以一种最复杂的方式开始。
直接拖拽控件到页面上(比如Default.aspx),然后设置一下它的RecordCount值就可以了。生成的页面代码如下:
// ... 略<%@ Register Src="UserControl/Pager.ascx" TagName="Pager" TagPrefix="uc1" %>// ... 略
我们也可以编写后置代码,然后来动态地使用它:
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { CustomPager pager = (CustomPager)LoadControl(@"~/UserControl/Pager.ascx"); pager.CssClass = "GreenStyle"; // 设置颜色 pager.UrlManager = new DefaultUrlManager("P"); // 设置根据Request.QueryString获取页码的参数 // 如果你实现了自己的IUrlManager接口,这里可能是这样: // pager.UrlManager = new YourUrlManger(); pager.RecordCount = 132; // 设置记录数 pager.PageSize = 7; // 设置分页大小 pager.PreviousPageCount = 3; // 设置当前页之前显示的最大链接数 pager.AfterPageCount = 3; // 设置当前也之后可以显示的最大链接数 // 将控件加入到页面上 phHolder.Controls.Add(pager); } }}
注意到这里,由于我们使用了新的CssClass样式,所以你也需要提供基于GreenStyle的样式表,我是这样提供的:
.GreenStyle a{ display:block; border:1px solid #9cba39; float:left; padding:4px 5px; text-decoration:none; text-align:center; margin:0 1px; color:#9cba39}.GreenStyle a.CurrentPage{ background:#C5D985; color:#fff;}.GreenStyle span{ position:relative; top:6px;}.GreenStyle span b{ color:#C33;}
本文我们实现了Asp.Net中的一个常见的功能,通过一个用户控件来实现数据分页的页面层以达到代码重用的目的。
我们通过实现 IUrlManager 接口来封装了不同情况下根据URL获取页码的方法。在用户控件中我们实现了主要的逻辑,并调用了实现IUrlManager的类的方法。最后,我们还看了如何通过CSS来控制控件的显示。
希望这篇文章能带给你帮助。来源:http://www.cnblogs.com/JimmyZhang/
赞