注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

我只是一个人

我爱一个人

 
 
 

日志

 
 

【引用】使用AspnetPager控件进行分页  

2011-03-02 21:13:24|  分类: 网页制作--技巧| |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    2个月没有学习了吧,这是第一篇技术的博客,还是写在这里吧,虽然网易的博客垃圾,但是不想换来换去。终于有一篇其他的博客了,不再是复复杂杂的感情! 

20070.2.2修改版 

    分页是Web应用程序中最常用到的功能之一,虽然GridView、FormView、DetailView控件都支持分页,但分页功能并不专业,而且样式不多;而且有时候我们需要对DataList、Repeater,甚至自定义数据绑定控件进行分页,就要手工书写分页代码。AspNetPager针对ASP.NET分页控件的不足,提出了与众不同的分页方案,即分页与数据显示功能的完全独立,因此使该控件适合于任何需要分页的数据绑定控件。另一个比较重要的是该控件支持URL分页方式[1]。使用下来,真的觉得AspnetPager是个不错的东西,而且是个开源的控件(谢谢作者分享他的知识),我目前使用的是6.0的版本。

下载和帮助可以访问http://www.webdiyer.com/AspNetPager/default.aspx

    在之前使用的安装版(忘了是几点几了)提供了两个工具来帮助生成分页存储过程和数据绑定的代码,webdiyer的网站也提供了这样的页面:http://www.webdiyer.com/AspNetPager/utility/sqlspgen.aspx个人感觉这两个工具还是不够灵活,而且目前不支持多表查询。再者,在学习的角度上也应该理解这个控件原理比较好,使用下来觉得自己真的学到不少东西,比较简单,建议稍微有点基础的程序员还是自己研究和编写代码的好,不要过分依赖工具。

AspnetPager控件的分页原理:

其实AspnetPager除了外观做得很好以外无非是提供了几个关键的属性,自身并没有分页的逻辑,也无需将控件与数据或数据控件进行绑定。分页的逻辑是需要另外编写分页存储过程或代码的,而这几个属性只是为分页存储过程和分页代码提供了参数,从而在控件的PageChanging事件触发时将属性结合存储过程取出一段一段的数据绑定给数据绑定控件现实。这几个关键的属性是RecordCount、CurrentPageIndex、PageSize。

I。编写分页存储过程

分页的存储过程网上可以找到很多,这里参考webdiyer推荐的存储过程讨论一下如何写AspnetPager使用的存储过程。存储过程应该有一个bit类型的参数:@docount,两个int型的参数:@pageindex(当前页索引)和@pagesize(每页显示记录数)。当@docount为1时表示返回当前数据表中要分页的所有记录的总数(RecordCount);当@docount设为0时,表示返回根据@pageindex和@pagesize两个参数计算出的当前页要显示的数据集,之所以这样,是因为在分页时AspNetPager必须首先知道要分页的记录的总数,AspNetPager根据该值和PageSize属性值来计算要显示数据的总页数,除非删除或添加了数据,否则该值只需在页面第一次加载时设置,AspNetPager会将该值保存在ViewState中,在其后页面回发时会从ViewState中取出该值,这样就不用每次分页时重新统计记录总数,可以大大提高分页性能。当然因为该存储过程每次都要判断@docount的值,对性能仍会有一定影响,所以如果你确定只想创建用来获取分页数据集而不统计记录总数的存储过程,可以省略@docount参数,但你需要另写一个存储过程或直接用Sql语句来获取要分页的记录总数,并在页面第一次加载(!postback)时将该存储过程或Sql语句的执行结果赋值给AspNetPager控件的RecordCount属性。当使用Url分页方式时,每次进行分页都需要页面重新加载而不是回发,所以每次都需要重新访问数据库统计记录总数,若数据量特别大时,分页速度会因此明显下降,一个好的解决办法是将所有要分页的记录总数保存在另一个表的一个字段中,当对分页的数据进行插入或删除操作时相应更新该字段的值,这样统计分页记录总数时只需获取该字段的值即可,相对于使用SQL count方法来统计所有记录总数,用这种方法可以明显提高分页效率。

webdiyer给出了三种方法来写分页存储过程,这三种方法大同小异,据说前两种在大数据量时又较第三种更好的性能,下面给出这3种方法的代码例子(代码是我根据自己的程序写的):

1。使用TABLE变量

CREATE procedure sp_search_line
(@pagesize int,
@pageindex int,
@docount bit)
as
set nocount on
if(@docount=1)
select count(qyid) from vw_onsalingtd
else
begin
declare @indextable table(id int identity(1,1),nid int)
declare @PageLowerBound int
declare @PageUpperBound int
set @PageLowerBound=(@pageindex-1)*@pagesize
set @PageUpperBound=@PageLowerBound+@pagesize
set rowcount @PageUpperBound
insert into @indextable(nid) select qyid from vw_onsalingtd order by qyid desc
select O.* from vw_onsalingtd O,@indextable t where O.qyid=t.nid
and t.id>@PageLowerBound and t.id<=@PageLowerBound  order by t.id
end
set nocount off
GO

2.使用临时表

CREATE procedure sp_search_line
(@pagesize int,
@pageindex int,
@docount bit)
as
set nocount on
if(@docount=1)
select count(qyid) from vw_onsalingtd
else
begin
declare @PageLowerBound int
declare @PageUpperBound int
set @PageLowerBound=(@pageindex-1)*@pagesize
set @PageUpperBound=@PageLowerBound+@pagesize
create table #pageindex(id int identity(1,1) not null,nid int)
set rowcount @PageUpperBound
insert into #pageindex(nid)
select qyid from vw_onsalingtd order by qyid desc
select O.*
from vw_onsalingtd O,#pageindex p
where O.qyid=p.nid and p.id>@PageLowerBound and p.id<=@PageUpperBound order by p.id
end
set nocount off
GO

3。使用多重Select语句

CREATE procedure sp_search_xl
(@pagesize int,
@pageindex int,
@docount bit)
as
set nocount on
declare @RecordCount int
select @RecordCount=count(qyid) from vw_onsalingtd
if(@docount=1)
select @RecordCount
else
begin
if(@pageindex=1)
exec('select top '+@pagesize+'* from vw_onsalingtd order by qyid desc')
else
begin
declare @PageUpperBound int
declare @endrecords int
set @PageUpperBound=@pageindex*@pagesize
if(@PageUpperBound-@pagesize)>=@RecordCount
select ''
else if(@RecordCount-(@PageUpperBound-@pagesize)<=@pagesize)
begin
set @endrecords=@RecordCount-(@PageUpperBound-@pagesize)
exec('select * from (select top '+@endrecords+' * from vw_onsalingtd order by qyid)A order by qyid desc')
end
else
exec('select * from (select top '+@pagesize+'* from (select top '+@PageUpperBound+' * from vw_onsalingtd order by qyid desc)A order by qyid)B order by qyid desc')
end
end
set nocount off
go

II。编写数据绑定代码

按照上面任何一种方法编写了分页的存储过程以后,当执行存储过程以后得到的就已经是分页后的数据了,所以数据访问只管保证存储过程的执行和执行后把结果绑定到控件上。不需要再考虑怎么实现分页。所以这种方法的重点就在存储过程这层。

SqlConnection conn;
SqlCommand cmd;
void Page_Load(object src,EventArgs e)

{
    conn=new SqlConnection(ConfigurationSettings.AppSettings["ConnStr"]);
    if(!Page.IsPostBack)

    {
        cmd=new SqlCommand("sp_search_xl",conn);
        cmd.CommandType=CommandType.StoredProcedure;
        cmd.Parameters.Add("@pageindex",1);
        cmd.Parameters.Add("@pagesize",1);
        cmd.Parameters.Add("@docount",true);
        conn.Open();
        AspNetpager1.RecordCount=(int)cmd.ExecuteScalar();//要把总记录数赋给RecordCount属性;
        conn.Close();
        BindData();
    }
}

//取出当前页下的数据段后绑定给DataList控件

void BindData(){
    cmd=new SqlCommand("sp_search_xl",conn);
    cmd.CommandType=CommandType.StoredProcedure;
    cmd.Parameters.Add("@pageindex",AspNetpager1.CurrentPageIndex);
    cmd.Parameters.Add("@pagesize",AspNetpager1.PageSize);
    cmd.Parameters.Add("@docount",false);
    conn.Open();
    DataList1.DataSource=cmd.ExecuteReader();
    DataList1.DataBind();
    conn.Close();
}

//分页事件,获得当前页数,触发新的BindData()方法
void ChangePage(object src,PageChangedEventArgs e){
    AspNetpager1.CurrentPageIndex=e.NewPageIndex;
    BindData();
}

---------------------------------这是以前用的方法,今天再用AspnetPager时找到了一个相对简单的方法,就是利用DataAdapter的填充方法(Fill())来进行分页。

代码如下:

------------------------------------在NewsManager类中的通用方法

/// <summary>
/// 取出经过分页后的数据表
/// </summary>
/// <param >取所有数据的查询语句</param>
/// <param >每页的数据条目数</param>
/// <param >AspNetPager控件</param>
/// <returns>经过分页后返回一个DataTable变量</returns>
public static DataTable GetPagedDataTable(string sqlQuery, int pageSize, Wuqi.Webdiyer.AspNetPager pager)
{
DataTable dt;
try
{
string connectString = Commen.ConnString();
SqlConnection con = new SqlConnection(connectString);
SqlCommand comm = new SqlCommand(sqlQuery, con);
con.Open();
SqlDataAdapter sqlda = new SqlDataAdapter(comm);
DataSet ds = new DataSet();
sqlda.Fill(ds);
pager.RecordCount = ds.Tables[0].Rows.Count;
pager.PageSize = pageSize;
sqlda.Fill(ds, pager.PageSize * (pager.CurrentPageIndex - 1), pager.PageSize, "tempTable");
con.Close();
sqlda.Dispose();
dt = ds.Tables["tempTable"];

//显示记录信息
pager.CustomInfoHTML = "评论总数:<font color=\"red\"><b>" + pager.RecordCount.ToString() + "</b></font>";
pager.CustomInfoHTML += " 总页数:<font color=\"red\"><b>" + pager.PageCount.ToString() + "</b></font>";
pager.CustomInfoHTML += " 当前页:<font color=\"red\"><b>" + pager.CurrentPageIndex.ToString() + "</b></font>";
}
catch (Exception ex)
{
throw new Exception("错误:"+ex.Message+"来自:"+ex.Source);
}
return dt;
}

-------------------其后的调用代码

protected void ChangePage(object src, Wuqi.Webdiyer.PageChangingEventArgs e)
{
commentPager.CurrentPageIndex = e.NewPageIndex;
int Id"]);
BindPagedCommentList(Id);
}

/// <summary>
/// 给GridView控件绑定分页评论数据
/// </summary>
/// <param >该条新闻的ID值</param>
protected void BindPagedCommentList(int newsId)
{
string sqlString = "SELECT * FROM YJ_Comment WHERE + newsId.ToString() + " ORDER BY ComId DESC";

//这里的sql语句很简单,不用用复杂的存储过程来处理分页的逻辑。
DataTable dt = NewsManager.GetPagedDataTable(sqlString, 10, commentPager);
GridView1.DataSource = dt.DefaultView;
GridView1.DataBind();
}

ps.[1]

什么是Url分页方式?

Url分页是把分页信息当作Url查询字串的一部分帮助分页的方法。用于分页的Url通常如:http://localhost:1522/YJWebSite/Articles/CommentInfo.aspx?Id=51&page=2Url分页方式允许用户通过在浏览器地址栏中输入相应的地址即可直接进入指定页面,也可以使搜索引擎搜索到所有分页的页面的内容,因此具有用户友好和搜索引擎友好的优点。

AspnetPager使用Url分页方式只要将属性UrlPaging="true"即可。

Url分页方式下的Url重写。Url重写分页允许不将分页信息写为查询字串的一部分,而是重构整个Url来携带分页信息,如给listpage.aspx下的数据分页,重写后的Url可能如:http://www.webdiyer.com/AspNetPager/demo/urlrewriting/listpage_2.aspxUrl重写技术可以使显示给用户的Url不同于实际的Url,Url重写技术被广泛应用于搜索引擎优化(SEO)、网站重组后重定向页面路径以及提供用户友好的Url等方面。

AspnetPager使用Url重写技术分页只要设置

UrlPaging="true"

EnableUrlRewriting="true"

UrlRewritePattern="./listpage_{0}.aspx"。 //可以选择自己制定的样式

PostBack分页与Url分页比较

  PostBack分页 Url分页
分页方式 通过页面回发来传递分页信息。 通过跳转到指定的Url来传递分页信息。
分页性能 可以将所有分页信息保存在ViewState中,如在页面初次加载时获取要分页的记录的总数,其后无需再次访问数据库获取该值,而可以从回发后的ViewState中获取,减少了数据库访问次数,提高了分页的速度。 每次分页时页面都被重新初始化,除通过Url传递的当前页索引外所有分页的数据都得重新获取,如每次分页都得从数据库获取所有要分页的记录的总数,因此速度较PostBack分页方式稍差。
灵活性 访问者可以动态改变分页属性,回发后仍可以保持改变后的属性值。 可以动态改变属性,但页面跳转后不会保留改变的属性值,而恢复为初始值。
直接访问 访问者无法通过输入Url访问除第一页外的其它页面。 访问者可以通过输入相应页面的Url访问任一页。
搜索引擎友好 搜索引擎只能检索第一页。 搜索引擎可以检索所有页。

ps.[2]

下面是自己写的一个完整的组合查询后的分页存储过程,给以后做参考用

alter procedure sp_search_qc
(@pagesize int,
@pageindex int,
@jg_str varchar(20),
@lx varchar(15),
@gjz varchar(50),
@zws int,
@docount bit)
as
set nocount on

declare @PageLowerBound int
declare @PageUpperBound int
declare @jg_low varchar(20)
declare @jg_up varchar(20)
declare @index int,@length int
set @PageLowerBound=(@pageindex-1)*@pagesize
set @PageUpperBound=@PageLowerBound+@pagesize
set @index=charindex(';',@jg_str)
set @length=len(@jg_str)
set @jg_low=substring(@jg_str,1,@index-1)
set @jg_up=substring(@jg_str,@index+1,@length-@index)

if(@docount=1)
select count(*)
from gys_qczlb as a, gysjbxxb as b,(select fwxmmxbh,max(xsje) 'qcbj' from GYSFWMXJGB group by fwxmmxbh) as c
where qcbj between convert(numeric(12,2),@jg_low) and convert(numeric(12,2),@jg_up)
      and cllx like '%'+@lx+'%'
      and a.fwxmmc like '%'+@gjz+'%'
      and zws>=@zws
      and a.gysbh=b.gysbh and a.fwxmmxbh=c.fwxmmxbh

else
begin
create table #pageindex(id int identity(1,1) not null,xmbh varchar(15))
set rowcount @PageUpperBound

insert into #pageindex(xmbh)

select a.fwxmmxbh
from gys_qczlb as a, gysjbxxb as b,(select fwxmmxbh,max(xsje) 'qcbj' from GYSFWMXJGB group by fwxmmxbh) as c
where qcbj between convert(numeric(12,2),@jg_low) and convert(numeric(12,2),@jg_up)
      and cllx like '%'+@lx+'%'
      and a.fwxmmc like '%'+@gjz+'%'
      and zws>=@zws
      and a.gysbh=b.gysbh and a.fwxmmxbh=c.fwxmmxbh
order by b.gysbh desc

select a.fwxmmc,a.zws,b.gysmc,c.qcbj,a.fwxmmxbh
from gys_qczlb a, gysjbxxb b, (select fwxmmxbh,max(xsje) as qcbj from gysfwmxjgb group by fwxmmxbh) c
where a.fwxmmxbh in (select xmbh from #pageindex where id>@PageLowerBound and id<=@PageUpperBound)
      and a.gysbh=b.gysbh and a.fwxmmxbh=c.fwxmmxbh
end
set nocount off

  评论这张
 
阅读(285)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018