zoukankan      html  css  js  c++  java
  • 【9】分页浏览的管理

    阅读目录

     

    分页关注的内容

    前面博文中,通过自行构造HTML表格代码,可以生成易于管理、易于扩展的数据列表。但在实际应用中,数据量动则成百上千,单一页面根本无法完全显示所有数据。把所有数据进行分页后逐页显示,是当前比较流行的数据展示方式。因此,我们需要研究和表格方式展示数据相适应的分页管理机制。

    分页显示的核心,是根据页面记录数、页号、查询条件、排序顺序等因素,在数据库中查出该页相对应的数据集(DataTable)。按页返回数据集的功能,已经作为一个基本的功能被封装到AccessDB中了,通过AccessDB.GetPage就可以直接获取。因此,我们只需要关心执行查询以外的各种管理和操作,包括以下方面:

    • 获取总记录集的记录数
    • 页码的有效性的检验
    • 查询条件的传递和应用
    • 向任意页面跳转的支持
    • 分页器的样式控制

    状态的传递

    分页管理的目的就是要对多个相互关联的页面进行管理,这些页面之间存在着联系,因此必须要能够把当前页面的某些重要状态传递给下一个页面。这些状态包括:

    • 数据表名
    • 当前页号
    • 页面大小
    • 当前查询条件
    • 当前排序条件

    ASPX有多种方式在页面间传递状态,如Cookie、Session、URL参数等。其中,以URL参数进行状态传递,是当前很多分页工具的普遍做法。综合考虑需求,使用URL传递参数,需要定义以下参数:

    • TableName
    • PageNo
    • PageSize
    • strWhere
    • strOrder

    分页的管理在页面中的体现就是分页器,即一组链接按钮和文字信息,通过它们可以了解当前分页信息,进行各种分页的跳转。有了上述的参数定义后,就可以定义分页的几个主要链接的形式。和前面的表格生成工具相一致,我们把分页器的HTML代码生成也封装到一个函数中:

    
    public string GetPager(int pagecount, int currentpage, string urlpara)
    {
    	string strPager = "";
    	strPager += "<a href='?PageNo=1" + urlpara + "'>首页</a>";
    	strPager += " <a href='?PageNo=" + (currentpage - 1 < 1 ? 1 : currentpage - 1).ToString() + urlpara + "'>上页</a>";
    	strPager += " " + currentpage.ToString() + "/" + pagecount.ToString();
    	strPager += " <a href='?PageNo=" + (currentpage + 1 > pagecount ? pagecount : currentpage + 1).ToString() + urlpara + "'>下页</a>";
    	strPager += " <a href='?PageNo=" + pagecount.ToString() + urlpara + "'>末页</a>";
    
    	return strPager;
    }
    

    通过语句调用:

    strContent += GetPager(20,1,"");

    达到HTML结果如下:

    
      <a href='?PageNo=1'>首页</a> <a href='?PageNo=1'>上页</a> 1/20 <a href='?PageNo=2'>下页</a> <a href='?PageNo=20'>末页</a>
    

    页面显示效果如下:

    image_thumb1

    对于分页器的构造方法而言,需要的参数,就是PageNo而已。但如果页面还有其他的参数,跳转链接应该同时把这些参数传递给下一个页面。因此,我们看到构造方法中有一个urlpara,就是用来传递其他的参数的。

    数据的获取

    通过传入的参数,就可以进行页面数据的获取了。获取记录的流程是:

    取得参数——查询总记录——判断范围,修正页码——查询记录集——构造分页器代码

    代码如下:

    
    protected void Page_Load(object sender, EventArgs e)
    {
    	//获取参数
    	int PageNo = Convert.ToInt32(Request.QueryString["PageNo"]);
    	int PageSize = 10;          //PageSize默认值为10
    	//获取总记录数
    	int RecordCount = AccessDB.GetCount("select * from book");
    	int PageCount = Convert.ToInt32(Math.Ceiling((double)RecordCount / PageSize));    
    	//有效性判断
    	if (PageNo < 1) PageNo = 1;
    	if (PageNo > PageCount) PageNo = PageCount;
    	//查询数据
    	DataTable dt = AccessDB.GetPage("select * from book",PageSize,PageNo,"ID",false );
    	//表格
    	strContent = Formater.FullTable(dt, "ID", "tblsample", "|出版年|书号|", "ID=编号;出版单位=出版社;", true, true, "书名", "showbook.aspx?id=KeyField", "del.aspx", "edit.aspx");
    	//分页器
    	strContent += GetPager(PageSize ,PageNo,"");
    }
    

    效果显示如下:

     image_thumb3

    上面的分页器的页面大小PageSize被设置为10,可以修改参数或者改造成为任意指定的大小,非常简单就不再详述了。另外,查询语句中,改用GetPage,同时sql语句不再限定条数了。

    查询结果的分页

    查询是数据管理的一个常用功能,查询浏览界面和数据浏览界面往往是同一个界面,或者说,查询功能本身就是数据浏览的一部分。对于查询的结果,也需要和浏览所有数据记录一致,采用相同的模式进行操作。所以分页管理必须要把查询综合考虑进来。

    如果是查询结果分页浏览,和前面的分页浏览有何不同呢?其实很容易看到,就是需要把上面的sql语句,增加一个查询条件即可。因此,查询分页,实质上就是把查询条件作为参数进行传递。

    另外,既然把Where子句进行参数传递,顺便把Order子句也进行传递,这样sql的大多数需求就能够满足了。

    在实际应用中,查询输入的条件往往是中文的,因此还需要对strWhere进行编码和解码,把中文转换成为URL可以识别的UTF8编码。

    对于上面的Demo页面,增加一个查询对话框,如下:

    image_thumb5

    查询按钮处理如下:

    
    //查询按钮事件
    protected void Button1_Click(object sender, EventArgs e)
    {
    	strWhere = " and 书名 like '%" + TextBox1.Text + "%'";
    	SetContent(); 
    }
    

    由于按钮事件的处理是在Page_Load之后,在Page_Load中已经对strContent进行了一次构造,这里必须重新构造strContent,所以把上面的构造方法放到一个单独的函数SetContent中,在Page_Load中调用一次,这里再调用一次,进行覆盖。

    另外,参数strWhere是一个页面级的变量,默认为空串,可以把参数保存起来,在调用SetContent时,取得这个参数并构造查询串。

    
    string strSQL = "select * from book";
    
    if (strWhere == "")  //没有最近的查询动作,检查有没有传递的参数
    {
    	if (Request.QueryString["strWhere"] != null)
    		strWhere =HttpUtility.UrlDecode( Request.QueryString["strWhere"].ToString());
    }
    strSQL += " where 1=1" + strWhere;
    
    //...
    
    //分页器
    strContent += GetPager(PageCount, PageNo, "&strWhere="+HttpUtility.UrlEncode(strWhere));
    

    上面代码中,strWhere有可能有多种情况:

    • 默认方式打开,为空串
    • 单击查询后的处理,为刚才设定的条件
    • 从分页器的链接传递而来,但是优先级要低于查询的条件

    下图是查询“名著”的结果,进行分页浏览的第四页,下方状态栏是鼠标放到“下页”的链接信息:

    image_thumb11

    跳页的实现

    除了按顺序浏览,很多页面数量往往非常巨大,因此分页器还需要支持跳页,可以向任意页面跳转。由于通过URL参数进行控制,实际非常简单,参数一修改即可。实现则需要通过js来实现。

    
    strPager += "<input name='GotoNum' type='text' id='GotoNum'/><a href="#" onclick="var url=document.URL;var gn=document.getElementById('GotoNum').value;if(gn!=''){if(url.indexOf('PageNo=')==-1){url=url +(url.indexOf('?')==-1?'?':'&')+ 'PageNo='+gn;}else{ url=url.replace('PageNo=', 'PageNo='+gn+'&wy='); }window.navigate(url);}" >跳转</a>";
    

    这样构造出的分页器就具备了跳转功能了!

    image_thumb15

    分页器的样式

    分页功能几乎是每个数据管理页面都需要的,但其样式总的来说,不会有太多的变化,因此,写好一个通用性较强的样式,就可以到处使用了。这是一个常用的分页器样式。

    
    <style type="text/css"">
    	 /** 分页 **/   
    	.pager{770px;text-align:center;margin:10px 0 10px 0;position:absolute;bottom:0px;} 
    	.pager a{display:inline-block;font-size:12px; 40px; background-color:#FFFFFF;padding:3px;text-align:center;border:1px #CCCCCC dotted;margin:0px 0px 2px 2px;}
    	.pager a:link,a:visited{ text-decoration:none;}
    	.pager a:hover{text-decoration:underline; background-color:#FF99FF;}
    	.pager #GotoNum{30px;}
    	.pager #reccount,.pager #pageinfo{display:inline-block;margin:0 5px 3px 5px;font-weight:bold;}
    </style>
    

    加上这个分页器后,将页面代码放到.pager的div中,效果如下:

    image_thumb17

    页面的完整的处理流程

    以下是页面的完成处理流程代码:

    
    public partial class book_pager_query : System.Web.UI.Page
    {
        protected string strContent;
        string strWhere="";
        protected void Page_Load(object sender, EventArgs e)
        {
            if(!Page.IsPostBack)
                SetContent();
        }
        private void SetContent()
        {
            string strSQL = "select * from book";
    
            if (strWhere == "")  //没有最近的查询动作,检查有没有传递的参数
            {
                if (Request.QueryString["strWhere"] != null)
                    strWhere =HttpUtility.UrlDecode( Request.QueryString["strWhere"].ToString());
            }
            strSQL += " where 1=1" + strWhere;
    
            //获取参数
            int PageNo = Convert.ToInt32(Request.QueryString["PageNo"]);
            int PageSize = 10;          //PageSize默认值为10
            //获取总记录数
            int RecordCount = AccessDB.GetCount(strSQL);
            int PageCount = Convert.ToInt32(Math.Ceiling((double)RecordCount / PageSize));
            //有效性判断
            if (PageNo < 1) PageNo = 1;
            if (PageNo > PageCount) PageNo = PageCount;
            //查询数据
            DataTable dt = AccessDB.GetPage(strSQL, PageSize, PageNo, "ID", false);
            //表格
            strContent = Formater.FullTable(dt, "ID", "tblsample", "|出版年|书号|", "ID=编号;出版单位=出版社;", true, true, "书名", "showbook.aspx?id=KeyField", "del.aspx", "edit.aspx");
            //分页器
            strContent +="<div class=pager>"+ GetPager(PageCount, PageNo, "&strWhere="+HttpUtility.UrlEncode(strWhere))+"</div>";
        }
        public string GetPager(int pagecount, int currentpage, string urlpara)
        {
            string strPager = "";
            strPager += "<a href="?PageNo=1" + urlpara + "">首页</a>";
            strPager += " <a href="?PageNo=" + (currentpage - 1 < 1 ? 1 : currentpage - 1).ToString() + urlpara + "">上页</a>";
            strPager += " " + currentpage.ToString() + "/" + pagecount.ToString();
            strPager += " <a href="?PageNo=" + (currentpage + 1 > pagecount ? pagecount : currentpage + 1).ToString() + urlpara + "">下页</a>";
            strPager += " <a href='?PageNo=" + pagecount.ToString() + urlpara + "'>末页</a>";
    
            strPager += "<input name='GotoNum' type='text' id='GotoNum'/><a href="#" onclick="var url=document.URL;var gn=document.getElementById('GotoNum').value;if(gn!=''){if(url.indexOf('PageNo=')==-1){url=url +(url.indexOf('?')==-1?'?':'&')+ 'PageNo='+gn;}else{ url=url.replace('PageNo=', 'PageNo='+gn+'&wy='); }window.navigate(url);}" >跳转</a>";
    
            return strPager;
        }
        //查询按钮事件
        protected void Button1_Click(object sender, EventArgs e)
        {
            strWhere = " and 书名 like '%" + TextBox1.Text + "%'";
            SetContent(); 
        }
    }
    

    GetPager的通用性较强,所以已经集成到CommonCode中了,通过Pager对象可以访问。

  • 相关阅读:
    洛谷P3959 宝藏(模拟退火乱搞)
    POJA Star not a Tree?(模拟退火)
    HDU 2899Strange fuction(模拟退火)
    洛谷P2062 分队问题(dp)
    主定理与时间复杂度
    android工程混淆和反编译
    查看linux内存、cpu
    Android sqlite数据库存取图片信息
    深入浅出JSONP--解决ajax跨域问题
    分析WordPress主题结构是如何架构的?
  • 原文地址:https://www.cnblogs.com/jetz/p/3754476.html
Copyright © 2011-2022 走看看