【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{width:770px;text-align:center;margin:10px 0 10px 0;position:absolute;bottom:0px;} 
	.pager a{display:inline-block;font-size:12px; width: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{width: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對象可以訪問。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM