zoukankan      html  css  js  c++  java
  • 【原创】ASP.NET通用分页

    一说到“分页”,大家可能不会很陌生,如果做过ASP.NET的,基本都做过,接触过分页,更有甚者更是精通。如果精通的分页的人就不用看这文章了。其内容也是平平。只是给刚接触分页和不是很了解分页的查看一下。

    通常分页分以下几种方式实现:

    (1)一些数据绑定控件自带的分页控件(例如GridView)

    (2)应用分页类PagedDataSource

    (3)用开源分页AspNetPager。它的功能也比较强大。

    (4)手动写前台Html和数据库的分页存储过程

    。。。等等。前三种方式不灵活,性能也有相应问题,个人比较倾向于第四种方式,它是自己可以控制的。

    我们在写分页时一定要考虑以下几个点。

    (1)效率问题与速度问题,数据量比较大时,不能一次性把数据加载到内存,而是需要哪一页的数据时,自动去加载需要的那一页数据。

    (2)通用性问题,我们写分页时,不能一直有相同的重复代码。最好封装起来。在任何页面都可以用。

    多余的就不说了。写这文章之前,也参考了网上写的比较好的例子。那么我就来总结一下吧。

    一种方式

    首先:建立一个Web用户控件(为了通用性嘛),代码如下:

     1 <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Pager3.ascx.cs" Inherits="PageS.Pager" %>
     2 
     3 
     4                 <asp:LinkButton ID="hylfirst" runat="server" onclick="reBind_Click">首页</asp:LinkButton>
     5                 <asp:LinkButton ID="hylprev" runat="server" onclick="reBind_Click">上一页</asp:LinkButton>
     6                 <asp:LinkButton ID="hylnext" runat="server" onclick="reBind_Click">下一页</asp:LinkButton>
     7                 <asp:LinkButton ID="hylend" runat="server" onclick="reBind_Click">尾页</asp:LinkButton>
     8                 
     9                 共<asp:Label ID="lbRecord" runat="server" Text="Label"></asp:Label>条记录
    10                 共<asp:Label ID="lbpage" runat="server" Text="Label"></asp:Label>11                 当前为第<asp:Label ID="lbRow" runat="server" Text=""></asp:Label>页

    后台:

     1  //当前页码
     2         private int _pageindex;
     3         public int PageIndex
     4         {
     5             get
     6             {
     7                 if (_pageindex == 0)
     8                 {
     9                     _pageindex = 1;
    10                 }
    11                 return _pageindex;
    12             }
    13             set { _pageindex = value; }
    14         }
    15         //一页的大小
    16         private int _pageSize;
    17         public int PageSize
    18         {
    19             get
    20             {
    21                 if (_pageSize == 0)
    22                 {
    23                     _pageSize = 1;
    24                 }
    25                 return _pageSize;
    26             }
    27             set { _pageSize = value; }
    28         }
    29         //总记录数
    30         private int _recordCount;
    31         public int RecordCount
    32         {
    33             get { return _recordCount; }
    34             set { _recordCount = value; }
    35         }            
    36 
    37         protected void Page_Load(object sender, EventArgs e)
    38         {
    39             if (!IsPostBack)
    40             {
    41                 LoadDataBind();
    42             }
    43         }
    44         //绑定
    45         public void LoadDataBind()
    46         {
    47             int pageCount = (RecordCount % PageSize) == 0 ? RecordCount / PageSize : RecordCount / PageSize + 1;//页数
    48           
    49             initialization(pageCount);
    50         }
    51         //数据初始化
    52         private void initialization(int pageCount)
    53         {
    54             //--------求出总记录数
    55             lbRecord.Text = RecordCount.ToString();
    56             //--------当前为第几页
    57             lbRow.Text = PageIndex.ToString();
    58             //--------共多少页      
    59             lbpage.Text = pageCount.ToString();
    60 
    61             this.hylfirst.Enabled = true;
    62             this.hylprev.Enabled = true;
    63             this.hylnext.Enabled = true;
    64             this.hylend.Enabled = true;
    65 
    66             if (Convert.ToInt32(this.lbRow.Text) == 1)
    67             {
    68                 this.hylfirst.Enabled = false;
    69                 this.hylprev.Enabled = false;
    70             }
    71             if (Convert.ToInt32(this.lbRow.Text) == pageCount)
    72             {
    73                 this.hylnext.Enabled = false;
    74                 this.hylend.Enabled = false;
    75             }
    76 
    77             this.hylfirst.CommandArgument = "1";
    78             this.hylprev.CommandArgument = (PageIndex - 1).ToString();
    79             this.hylnext.CommandArgument = (PageIndex + 1).ToString();
    80             this.hylend.CommandArgument = pageCount.ToString();
    81 
    82         }
    83 
    84         //定义一个委托
    85         public delegate void reBindEvent(object sender, EventArgs arg);
    86         public event reBindEvent reBind;
    87 
    88         protected void reBind_Click(object sender, EventArgs e)
    89         {
    90             if (this.reBind != null)
    91                 this.reBind(sender, e);
    92             LoadDataBind();
    93         }

    说明:在代码的最后利用了委托和事件。这是为什么呢。因为我们在点击自定义控件的按扭(上一页,下一页,首页,未页.....)时,要调用Aspx页面绑定数据的方法。我们在这里不能直接实例化aspx页面类,再去调用其方法。

    我们为了通用必须这样去做。有关ASPX和自定义控件之间的赋值,互相调用,大家可以去网上找此资料来看,本章不讲解这些内容。

    好了,我们已经做好通用性了,那么我们如何调用呢。

    建立一个测试页面,代码如下:

     1 <%@ Register src="Pager.ascx" tagname="Pager" tagprefix="uc1" %>
     2 
     3 
     4 
     5 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     6 
     7 <html xmlns="http://www.w3.org/1999/xhtml" >
     8 <head runat="server">
     9     <title>利用反射机制</title>
    10 </head>
    11 <body>
    12     <form id="form1" runat="server">
    13     <div>
    14         <asp:GridView ID="gvUsers" runat="server" ></asp:GridView>     
    15         <uc1:Pager ID="Pager1" runat="server" OnreBind="LoadData" />
    16             
    17     </div>
    18   
    19        
    20     </form>
    21 </body>
    22 </html>

    后台:

     1    protected void Page_Load(object sender, EventArgs e)
     2         {
     3             if (!IsPostBack)
     4             {             
     5                 LoadData(null,null);
     6             }
     7         }
     8         protected void LoadData(object sender, EventArgs e)
     9         {
    10             if (sender != null)
    11             {
    12                 Pager1.PageIndex = Convert.ToInt32(((LinkButton)sender).CommandArgument);
    13             }
    14             else
    15             {
    16                 Pager1.PageIndex = 1;
    17             }
    18             int recordcount = 0;
    19             Pager1.PageSize = 20;
    20            
    21             DataTable tables=new DataTable();
    22             
    23             //通过当前页码,页大小,去数据库调用本页的数据,并且返回总记录数
    24             //tables=  BLL.GetCurrentPageData(Pager1.PageIndex, Pager1.PageSize,out count);           
    25             
    26             gvUsers.DataSource = tables;
    27             gvUsers.DataBind();
    28             Pager1.RecordCount = recordcount;
    29 
    30 
    31         }

    说明: <uc1:Pager ID="Pager1" runat="server" OnreBind="LoadData" /> 看到OnreBind="LoadData"了吗, 这个是我们在自定义控件中定义的事件。在这个订阅一下。

    以便在自定义控件中点击按扭时,自动来触发这个事件。从而调用LoadData这个方法。

    说了半天,好像还没出给出数据库分页的通用存储过程来。

    好了,那我也直接粘出来供大家来分享吧。单表的通用分页存储过程

    CREATE PROCEDURE [dbo].[_tgy_BaseGetPageList] 
    (
        @tblName varchar(255),             -- 表名
        @strGetFields varchar(1000) = '*',     -- 需要返回的列 
        @fldName varchar(255) = '',         -- 排序的字段名
        @PageSize int = 10,             -- 页尺寸
        @PageIndex int = 1,             -- 页码
        @doCount bit = 0,             -- 返回记录总数, 非 0 值则返回
        @OrderType bit = 0,             -- 设置排序类型, 非 0 值则降序
        @strWhere varchar(1500) = ''        -- 查询条件 (注意: 不要加 where)
    )
    AS
      declare @strSQL varchar(5000) -- 主语句
      declare @strTmp varchar(110) -- 临时变量
      declare @strOrder varchar(400) -- 排序类型
    
      if @doCount != 0
        begin
            if @strWhere !=''
                  set @strSQL = 'select count(*) as Total from ' + @tblName + ' where ' + @strWhere
            else
                  set @strSQL = 'select count(*) as Total from ' + @tblName + ''
            end 
     
        --以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况:
    
      else
            begin
            if @OrderType != 0
                begin
                    set @strOrder = ' order by ' + @fldName + ' desc'
                    --如果@OrderType不是0,就执行降序,这句很重要!
                end
            else
                begin
                    set @strOrder = ' order by ' + @fldName
                end
    
            if (@PageIndex = 1 or @PageIndex = 0)
                begin
                    if @strWhere != '' 
                        set @strSQL = 'select top ' + str(@PageSize) + ' ' 
                            + @strGetFields 
                            + 'from ' + @tblName 
                            + ' where ' + @strWhere 
                            + ' ' + @strOrder
                    else
                        set @strSQL = 'select top ' + str(@PageSize) + ' ' 
                            + @strGetFields 
                            + 'from ' + @tblName 
                            + ' ' + @strOrder
                --如果是第一页就执行以上代码,这样会加快执行速度
                end
            else
                begin
                --以下代码赋予了@strSQL以真正执行的SQL代码 
                    set @strSQL = 'select top ' + str(@PageSize) + ' ' 
                                + @strGetFields 
                                + ' from '
                                + ' ( select '+ @strGetFields
                                + ' ,Row_Number() OVER('+@strOrder+') as row' 
                                + ' from ' + @tblName 
                                + ' ) aaa'
                                + ' where row > ' + str((@PageIndex-1)*@PageSize)
                    if @strWhere != ''
                        set @strSQL = 'select top ' + str(@PageSize) + ' ' 
                                    + @strGetFields 
                                    + ' from '
                                    + ' ( select '+ @strGetFields
                                    + ' ,Row_Number() OVER('+@strOrder+') as row' 
                                    + ' from ' + @tblName 
                                    + ' where ' + @strWhere + ' ) aaa'
                                    + ' where row > ' + str((@PageIndex-1)*@PageSize)
                end 
    
        end 
    
    exec (@strSQL)

    有的人一看,怎么就针对一张表呢,我在写存储过程的时候很多时候会涉及多张表,这个也不通用呀。好了,毕竟网上有能人。我直接粘下代码。多表通用分页存储过程

      1 CREATE PROCEDURE [dbo].[Proc_SplitPage]   
      2 (  
      3 @tblName     nvarchar(200),        ----要显示的表或多个表的连接  
      4 @fldName     nvarchar(1000) = '*',    ----要显示的字段列表  
      5 @pageSize    int = 10,        ----每页显示的记录个数  
      6 @page        int = 1,        ----要显示那一页的记录  
      7 @fldSort    nvarchar(200),    ----排序字段列表或条件  
      8 @Sort        bit = 0,        ----排序方法,0为升序,1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记)--程序传参如:' SortA Asc,SortB Desc,SortC ')  
      9 @strCondition    nvarchar(2000) = null,    ----查询条件,不需where  
     10 @ID        nvarchar(150),        ----主表的主键  
     11 @Dist                 bit = 0,           ----是否添加查询字段的 DISTINCT 默认0不添加/1添加  
     12 @pageCount    int = 1 output,            ----查询结果分页后的总页数  
     13 @Counts    int = 1 output              ----查询到的记录数  
     14 )  
     15 AS  
     16 SET NOCOUNT ON  
     17 Declare @sqlTmp nvarchar(1000)        ----存放动态生成的SQL语句  
     18 Declare @strTmp nvarchar(4000)        ----存放取得查询结果总数的查询语句  
     19 Declare @strID     nvarchar(1000)        ----存放取得查询开头或结尾ID的查询语句  
     20   
     21 Declare @strSortType nvarchar(10)    ----数据排序规则A  
     22 Declare @strFSortType nvarchar(10)    ----数据排序规则B  
     23   
     24 Declare @SqlSelect nvarchar(50)         ----对含有DISTINCT的查询进行SQL构造  
     25 Declare @SqlCounts nvarchar(50)          ----对含有DISTINCT的总数查询进行SQL构造  
     26   
     27   
     28 if @Dist  = 0  
     29 begin  
     30     set @SqlSelect = 'select '  
     31     set @SqlCounts = 'Count(*)'  
     32 end  
     33 else  
     34 begin  
     35     set @SqlSelect = 'select distinct '  
     36     set @SqlCounts = 'Count(DISTINCT '+@ID+')'  
     37 end  
     38   
     39   
     40 if @Sort=0  
     41 begin  
     42     set @strFSortType=' ASC '  
     43     set @strSortType=' DESC '  
     44 end  
     45 else  
     46 begin  
     47     set @strFSortType=' DESC '  
     48     set @strSortType=' ASC '  
     49 end  
     50   
     51 --------生成查询语句--------  
     52 --此处@strTmp为取得查询结果数量的语句  
     53 if @strCondition is null or @strCondition=''     --没有设置显示条件  
     54 begin  
     55     set @sqlTmp =  @fldName + ' From ' + @tblName  
     56     set @strTmp = @SqlSelect+' @Counts='+@SqlCounts+' FROM '+@tblName  
     57     set @strID = ' From ' + @tblName  
     58 end  
     59 else  
     60 begin  
     61     set @sqlTmp = + @fldName + 'From ' + @tblName + ' where (1>0) ' + @strCondition  
     62     set @strTmp = @SqlSelect+' @Counts='+@SqlCounts+' FROM '+@tblName + ' where (1>0) ' + @strCondition  
     63     set @strID = ' From ' + @tblName + ' where (1>0) ' + @strCondition  
     64 end  
     65   
     66   
     67   
     68 ----取得查询结果总数量-----  
     69 exec sp_executesql @strTmp,N'@Counts int out ',@Counts out  
     70 declare @tmpCounts int  
     71 if @Counts = 0  
     72     set @tmpCounts = 1  
     73 else  
     74     set @tmpCounts = @Counts  
     75   
     76     --取得分页总数  
     77     set @pageCount=(@tmpCounts+@pageSize-1)/@pageSize  
     78   
     79     /**//**当前页大于总页数 取最后一页**/  
     80     if @page>@pageCount  
     81         set @page=@pageCount  
     82   
     83     --/*-----数据分页2分处理-------*/  
     84     declare @pageIndex int --总数/页大小  
     85     declare @lastcount int --总数%页大小   
     86   
     87     set @pageIndex = @tmpCounts/@pageSize  
     88     set @lastcount = @tmpCounts%@pageSize  
     89     if @lastcount > 0  
     90         set @pageIndex = @pageIndex + 1  
     91     else  
     92         set @lastcount = @pagesize  
     93   
     94     --//***显示分页  
     95     if @strCondition is null or @strCondition=''     --没有设置显示条件  
     96     begin  
     97         if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理  
     98             begin   
     99                 set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName  
    100                         +' where '+@ID+' not in('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName  
    101                         +' order by '+ @fldSort +' '+ @strFSortType+')'  
    102                         +' order by '+ @fldSort +' '+ @strFSortType   
    103             end  
    104         else  
    105             begin  
    106             set @page = @pageIndex-@page+1 --后半部分数据处理  
    107                 if @page <= 1 --最后一页数据显示  
    108                     set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@lastcount as VARCHAR(4))+' '+ @fldName+' from '+@tblName  
    109                         +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType   
    110                 else                  
    111                     set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName  
    112                         +' where '+@ID+' not in('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName  
    113                         +' order by '+ @fldSort +' '+ @strSortType+')'  
    114   
    115                         +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType   
    116             end  
    117     end  
    118   
    119     else --有查询条件  
    120     begin  
    121         if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理  
    122         begin   
    123                 set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName +' from  '+@tblName  
    124                     +' where '+@ID+' not in('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName  
    125                     +' Where (1>0) ' + @strCondition + ' order by '+ @fldSort +' '+ @strFSortType+')'  
    126                     +' ' + @strCondition + ' order by '+ @fldSort +' '+ @strFSortType                   
    127         end  
    128         else  
    129         begin   
    130             set @page = @pageIndex-@page+1 --后半部分数据处理  
    131             if @page <= 1 --最后一页数据显示  
    132                     set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@lastcount as VARCHAR(4))+' '+ @fldName+' from '+@tblName  
    133                         +' where (1>0) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType  
    134             else  
    135                     set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName  
    136                         +' where '+@ID+' not in('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName  
    137                         +' where (1>0) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+')'  
    138                         + @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType   
    139         end      
    140     end  
    141   
    142 ------返回查询结果-----  
    143 exec sp_executesql @strTmp    
    144 --print @strTmp  
    145 SET NOCOUNT OFF  
    146   

     本文就更新到这里,后台也会有我其它的分页实现,以上代码中涉及自定义控件调用aspx类的方法,其实也可以用反射机制来实现,大家试试吧。以后我也会涉及。可能也有人对怎么使用通用存储过程也有疑问,我也会在接下来的几篇文章中细讲。

    Ok,本文结束:

     转载的请注原创地址,谢谢。

  • 相关阅读:
    搭建自己的SIPserver:开源sipserveropensips的搭建及终端TwInkle的使用
    字符串类习题、面试题具体解释(第二篇)
    【Android笔记】MediaPlayer基本使用方式
    poj 1258 Agri-Net
    ActionScript3游戏中的图像编程(连载二十四)
    SQL中declare申明变量
    CreateFileMapping使用方法
    【剑指offer】调整数组顺序
    2015美团网笔试面试总结(嵌入式/硬件类)(美团网校园招聘)
    linux串口驱动分析
  • 原文地址:https://www.cnblogs.com/yxhblog/p/2570020.html
Copyright © 2011-2022 走看看