zoukankan      html  css  js  c++  java
  • 分页控件 实战 Post篇

    前言:

    分页,大伙并不陌生
    也许你正用着:DataGrid/GridView自带的分页
    也许你正用着:网上流传较广的AspnetPager分页控件
    也许你正用着:其它同事写的分页控件
    又也许:你正是那个写分页控件的人,如果是,现在的你是否回头看过自己当初的源码?感觉?

    附言:

    昨夜,花了两个小时左右,把一个2007年那会写的分页控件,重新优化改造了一下:
    cs代码大小从原来的14K,缩减到4K。
    原来的分页控件源码:点击下载
     
    在看以下正文之前,还是希望能看一下原来的分页控件的源码,这样才能感叹下改造前后的巨大落差。

    正文:

    一:概述

    目前分页控件,据个人所知的,有几下几种实现情况:

    1:Post篇 [生成N个按钮,每个按钮点击时产生一个Post事件引发分页]

    常见方式:控件实现复杂,内渗杂sql语句。
    本文方式:反射机制,与sql无关。
    遥想当年是配合了atlas的updatepanel实现的无刷新

    2:Get篇 [生成N个链接,每个链接点击时产生一个Get事件引发分页]

    方式一:链接分页,常见于参数后面的page=N
    方式二:链接分页,Url重写,常见于url参数为 /page/N
    方式三:脚本分页,无刷新,链接都采用onclick="js函数"引发ajax回调异步分页。

    二:实现

    在具体写实现代码之前,我们上几张图片看一下效果:

    说明:

    昨夜把代码上传到网络空间时,忘了把样式也传上去,早上下载后发现没样式。

    所以样式是自己临时加上去的,大伙自己感知一下效果了就可以了。

    下面开始分页控件实现具体步骤:

    1:新建一个用户控件:Pager

    2:控件前台html

    <table id="pager" border="0" cellpadding="0" cellspacing="0" width="100%">
        
    <tr>
            
    <td>
                
    <asp:LinkButton ID="lbtnFirstLink" runat="server" CausesValidation="false" OnClick="ClickEvent">首页</asp:LinkButton>
                
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false"  OnClick="ClickEvent">上一页</asp:LinkButton>
        
                
    <asp:Repeater ID="rptNum" runat="server" OnItemCommand="rptNum_ItemCommand">
                    
    <ItemTemplate>
        
    <asp:LinkButton ID="lbtnNum" runat="server" CausesValidation="false" CommandArgument='<%# Container.DataItem %>'
        CssClass='
    <%# Convert.ToInt32(Container.DataItem)==PageIndex?"num_yellow":"num_blue"%>' Width="15"><%# Container.DataItem %>
    </asp:LinkButton>
                    
    </ItemTemplate>
                
    </asp:Repeater>
          
                
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false"  OnClick="ClickEvent">下一页</asp:LinkButton>
                
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false"  OnClick="ClickEvent">尾页</asp:LinkButton>
                
    <asp:HiddenField ID="hfBindName" runat="server" />
            
    </td>
        
    </tr>
    </table>

    说明:

    A:用了表格布局,简单,想换div的自己改了。
    B:用了五个LinkButton,其中数字的一个用Repeater循环N个数字出来
    C:最后加了一个隐藏域,用于保存绑定的方法名称。
    D:数字里有两个样式用于为数字赋样式,样式到示例时再写出来吧
    E:首页/上一页/下一页/尾页,用的点击事件都是同一个函数。
    F:Repeater有个OnItemCommand事件,点击数字要重新绑定的。

    3:后台cs代码

    A:几个属性

        private int _PageIndex;
        
    public int PageIndex
        {
            
    get{if (_PageIndex == 0){ _PageIndex = 1;}return _PageIndex;}
            
    set{ _PageIndex = value;}
        }    
        
    private int _PageSize;
        
    public int PageSize
        {
            
    get{if (_PageSize == 0){_PageSize = 1;}return _PageSize;}
            
    set{ _PageSize = value;}
        }
        
    private int _Count;
        
    public int Count
        {
            
    get{return _Count; }
            
    set { _Count = value; }
        }
        
    /// <summary>
        
    /// 该方法名称修饰符为需为public
        
    /// </summary>
        public string BindName
        {
            
    get{return hfBindName.Value;}
            
    set{hfBindName.Value = value; }
        }

    说明:

    PageIndex:第几页
    PageSize:每页多少条
    Count:记录总数
    BindName:绑定的方法名称,用于反射绑定数据

    B:Page_Load做点什么

    private void Page_Load(object sender, System.EventArgs e)
    {
            
    if (!Page.IsPostBack)
            {
                BindPager();
    //绑定分页数字
            }
    }

    说明:

    第一次绑定时,界面已实现绑定数据,所以只需要绑定分页的数字就行了

    C:绑定分页数字

    public void BindPager()
    {
            
    int pageCount = (Count % PageSize) == 0 ? Count / PageSize : Count / PageSize + 1;//页数
            SetButtonEnable(pageCount);//下面四个按钮可用状态设置
            BindPageNum(pageCount);//绑定循环数字
    }

    说明:

    1:从记录总数和页面大小计算出有多少页,这个少不的。
    2:根据当页的页数和当前页面索引,设置下“首页/下一页/上一页/尾页”的可用状态
    3:根据当前的页数绑定一下循环的数字。

    函数分解:SetButtonEnable [设置按钮可用状态及参数赋值]

    private void SetButtonEnable(int pageCount)
    {
            lbtnFirstLink.Enabled 
    = PageIndex != 1;
            lbtnPrevPage.Enabled 
    = PageIndex != 1;
            lbtnNextPage.Enabled 
    = PageIndex != pageCount;
            lbtnLastPage.Enabled 
    = PageIndex != pageCount;
            lbtnFirstLink.CommandArgument 
    = "1";
            lbtnPrevPage.CommandArgument 
    = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument 
    = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument 
    = pageCount.ToString();
    }

    说明:

    1:如果当前页为第1页:首页/上一页状态不可用
    2:如果当前页为最后1页:下一页/尾页状态不可用
    3:顺路把几个页索引值赋给CommandArgument

    函数分解:BindPageNum [绑定分页数字]

    protected void BindPageNum(int pageCount)
    {
            
    int start = 1, end = 10;
            
    if (pageCount < end)//页数小于10
            {
                end 
    = pageCount;
            }
            
    else
            {
                start 
    = (PageIndex > 5? PageIndex - 5 : start;
                
    int result = (start + 9- pageCount;//是否超过最后面的页数
                if (result > 0)
                {
                    end 
    = pageCount;
                    start 
    -= result;//超过后,补差
                }
                
    else
                {
                    end 
    = start + 9;
                }
            }
            ReBindNum(start, end);
    }

    说明:

    1:由于绑定的数字,在往后页数点击时,页数数字需要进行变化,所以需计算好开始数字和结束数字
    2:根据开始数字和结束数字进行绑定

    函数分解:ReBindNum [循环绑定数字]

    private void ReBindNum(int start, int end)
    {
            
    int[] rows = new int[end-start+1];//这里之前写10,修正为end-start+1。
            
    int index = 0;
            
    for (int i = start; i <= end; i++)
            {
                rows[index] 
    = i;
                index
    ++;
            }
            rptNum.DataSource 
    = rows;
            rptNum.DataBind();
     }

    说明:

    1:这里用int[]数组循环数字来绑定到Repeater
    2:界面绑定用
    <%# Container.DataItem %>方式进行对应

    D:反射绑定[简洁重点函数]

    private void ReBindData(string pageIndex)
    {
            PageIndex = int.Parse(pageIndex);
            object obj = base.Parent is HtmlForm ? this.Page : base.Parent;
            MethodInfo mi = obj.GetType().GetMethod(BindName);
            mi.Invoke(obj,null);
            BindPager();
    }

    说明:

    1:重点在于区分,分页控件是直接在页面中使用,还是在控件套分页控件的方式使用
    2:获取绑定数据的方法,重新调用一下
    3:重新绑定分布数字

    F:首页/上一页/下一页/尾页,按钮事件

    protected void ClickEvent(object sender, EventArgs e)
    {
            ReBindData(((LinkButton)sender).CommandArgument.ToString());
    }

    G:分页数字,按钮事件

    protected void rptNum_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
       ReBindData(e.CommandArgument.ToString());
    }

    三:示例代码,和 CYQ.Data轻量数据层框架 配合使用

    1:html代码

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="PagerDemo.aspx.cs" Inherits="PagerDemo" EnableTheming="false" %>
    <%@ Register Src="UserControls/Pager.ascx" TagName="Pager" TagPrefix="uc1" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        
    <title>路过秋天 分页控件演示</title>
        
    <style type="text/css">
        #pager 
    {color:White;}
        #pager a
    {color:White;text-decoration:none; }
        .num_blue
    {color:White;border:solid 1px Blue;text-align:center;}
        .num_yellow
    {color:while;border:solid 1px Yellow; text-align:center;}
        
    </style>
    </head>
    <body style="background-color:Black;color:White;">
        
    <form id="form1" runat="server">
        
    <div><asp:GridView ID="gvUsers" runat="server"></asp:GridView><br />
            
    <uc1:Pager ID="Pager1" runat="server" />
        
    </div>
        
    </form>
    </body>
    </html>

    2:后台代码

    protected void Page_Load(object sender, EventArgs e)
    {
            
    if (!IsPostBack)
            {
                LoadData();
            }
    }
    public void LoadData()
    {
            
    int count;
            MAction action 
    = new MAction(TableNames.Users);
            MDataTable mTable 
    = action.Select(Pager1.PageIndex, Pager1.PageSize, ""out count);
            action.Close();
            gvUsers.DataSource 
    = mTable;
            gvUsers.DataBind();
            Pager1.BindName 
    = "LoadData";
            Pager1.Count 
    = count;
    }

    说明:

    1:BindName为绑定数据的方法名称,该方法名称的修饰符号需为public
    2: 默认的分页PageSize可自行修改默认值
    3: 前面html也可设置为:
    <uc1:Pager ID="Pager1" runat="server" PageSize="20" />

    3:最终效果

    如正文一开始发的五张图片一致

    结言:

    以上教程中,以包含所有代码,包括前后台,所以不另提供打包下载。
    有兴趣的来客欢迎讨论留言。

    源码下载地址:http://www.cyqdata.com/download/article-detail-28683

    版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
    个人微信公众号
    创业QQ群:617713515
    Donation(扫码支持作者):支付宝:
    Donation(扫码支持作者):微信:
  • 相关阅读:
    【HDU 4305】Lightning(生成树计数)
    【HDU 1150】Machine Schedule(二分图匹配)
    【HDU 2063】过山车(二分图匹配)
    透过Nim游戏浅谈博弈
    [SCOI2010]字符串
    [SCOI2010]传送带[三分]
    [SCOI2010]序列操作[分块or线段树]
    HDU 5306 Gorgeous Sequence[线段树区间最值操作]
    1455: 罗马游戏[左偏树or可并堆]
    Codevs 5914 [SXOI2016]最大值
  • 原文地址:https://www.cnblogs.com/cyq1162/p/1812361.html
Copyright © 2011-2022 走看看