All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
ASP.NET,2.0的Web,Part,Framework_[Asp.Net教程]
在PHP中执行系统外部命令_[PHP教程]
ASP.NET,2.0角色及成员管理_[Asp.Net教程]
SQL,Server单引号的两种处理技巧_[SQL,Server教程]
让你的.NET应用成为一个灰色盒子_.net资料_编程技术
DataSet数据导入Excel的c#代码_[Asp.Net教程]
利用XMLHTTP无刷新添加数据之Get篇_[XML教程]
用.NET实现所见即所得的设计器_[Asp.Net教程]
ASP.NET,2.0中保证应用程序的安全_.net资料_编程技术
delphi中break语句与continue语句的比较
Reading number is top 10 pictures
The money of more than 100 countries and regions7
Breasts woman big set 1
From China fortress sora aoi3
NeedWallpaper5
寒流来了
The little girl with long hair3
影评-疯子,我爱你
Household design comfortable contracted
西游四格漫画(五)
何炅哥为中国人的平均工资鸣不平了
Download software ranking
传奇私服架设教程
都市狐狸姑娘传
Red cliff
Boxer Classic video3
Unix video tutorial20
Boxer vs Yellow1
双旗镇刀客B
Professional killers2 for Android
VeryCD电驴(EasyMule) V1.1.9 Build09081
SP3 for SQL2000
归海一刀 published in(发表于) 2014/1/30 0:53:16 Edit(编辑)
Asp.Net,可自定义分页用户控件_[Asp.Net教程]

Asp.Net,可自定义分页用户控件_[Asp.Net教程]

Asp.Net 可自定义分页用户控件_[Asp.Net教程]

介绍


借助 Asp.Net 提供的数据绑定控件,我们无需太多的代码,甚至不需要代码,只要在 VS2005 中拖拽几下控件,进行一些属性的设置,便可以实现在Asp时代需要做大量工作才能够实现的分页功能。但在实际的应用中,尤其是在Web站点程序中,我们经常需要更加丰富的用户界面,而类似DataList或者 GridView 这样的数据控件往往不能或者很难满足我们的要求。此时,我们常常求助于 Repeater 控件,这样我们依旧会面临分页及其显示的问题。


本文不是讲述如何进行数据库分页,而将注意力集中在如何实现可定制地 获取页码、获取路径、显示分页链接,并且通过构建一个用户控件来实现代码重用上。这个用户控件我自己正在使用,如果你是一个初学者,你可以借鉴一下我的实现方式;如果你已经是一位高手,不妨提出设计的不足和改进意见。


控件组成


为了能迅速提起大家的兴趣,可以先点击这个链接,看看实际的效果:


http://www.tracefact.net/Demo/Pager/Default.aspx


IUrlManager 接口


想一想如果你在设计一个可重用的分页用户控件,你面临的问题是什么?每个人获取页码的方式都不同,例如,你的站点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); // 根据 页码 获取页面路径
}


DefaultUrlManager 类


现在 所有获取页码 及 根据页码获取路径 的逻辑都可以放在实现了这个接口的类中。如果你想使用这个控件,你需要提供一个实现了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 文件


由于我们的链接是动态生成的,所以我们大部分的代码都会存在于 Pager.ascx.cs 中,在Pager.ascx 文件中,我们只提供一个装链接的容器:


<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Pager.ascx.cs" Inherits="CustomPager" %>


Pager.ascx.cs 文件


我们对于页面的显示的主要实现都放置在了这个文件中,我在文件中做了大量注释,这里就不再文字描述了:


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 = "&lt;&lt;";
first.ToolTip = "第一页";
first.NavigateUrl = urlManager.GetPageUrl(1);
pnPager.Controls.Add(first);

HyperLink previous = new HyperLink();
previous.CssClass = "PagerIcon";
previous.Text = "&lt;";
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 = "&gt;";
next.ToolTip = "下一页";
next.NavigateUrl = urlManager.GetPageUrl(currentPage + 1);
pnPager.Controls.Add(next);

HyperLink last = new HyperLink();
last.CssClass = "PagerIcon";
last.Text = "&gt;&gt;";
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/







添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.