出處:http://www.dotblogs.com.tw/shadow/archive/2011/11/28/59816.aspx
承接此篇的範例:[ASP.net WebForm] 使用PagedDataSource物件實現手寫分頁 (適合初學者)
這次要把分頁區塊包在WebUserControl,讓之後其他的 *.aspx有ListView或GridView的畫面,只要一拉進WebUserControl,就可以馬上做分頁
對著專案新增項目
[檢視圖片]
接著就是做搬移程式碼的動作
pageListViewOrGridView.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="pageListViewOrGridView.ascx.cs" Inherits="pageListViewOrGridView" %> <style type="text/css"> /*分頁區塊的CSS*/ .rsmenu { color: #4c4c4c; padding: 15px 0; clear: both; text-align: center; } .rsmenu span, .rsmenu span a { color: #808e02; } .pgbtn { background: #808E02; border: none medium; color: #fff; cursor: pointer; width: 40px; height: 19px; } .pgbtn:hover { background: #99a535; } </style> <%--分頁區塊--%> <div class="rsmenu"> 合計<asp:Literal ID="li_totalRows" runat="server" /> <span>| <asp:LinkButton Text="最前頁" ID="lnkFirstPage" runat="server" OnClick="lnkFirstPage_Click" /> | <asp:LinkButton Text="上一頁" ID="lnkPrePage" runat="server" OnClick="lnkPrePage_Click" />| </span>選擇頁數 <b>第<asp:DropDownList runat="server" ID="dl_currentPage"> </asp:DropDownList> 頁</b> <span>| <asp:LinkButton Text="下一頁" ID="lnkNextPage" runat="server" OnClick="lnkNextPage_Click" />| <asp:LinkButton Text="最後頁" runat="server" ID="lnkLastPage" OnClick="lnkLastPage_Click" />| </span>每頁 <asp:DropDownList runat="server" ID="dl_pageSize"> <asp:ListItem Value="5" Text="5" /> <asp:ListItem Value="10" Text="10" /> </asp:DropDownList> 筆 <asp:Button ID="btnToPage" runat="server" CssClass="pgbtn" Text="跳頁" OnClick="btnToPage_Click" /> </div>
.ascx的Code-Behind(未完整)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; /*要引用以下三個命名空間*/ using System.Data; using System.Data.SqlClient; using System.Web.Configuration; public partial class pageListViewOrGridView : System.Web.UI.UserControl { //連線字串 string connStr = WebConfigurationManager.ConnectionStrings["connStr"].ConnectionString; protected void Page_Load(object sender, EventArgs e) { } #region 分頁資料,總筆數、總頁數文字顯示處理 protected void showData(int currentPage, int pageSize, string sql) { DataSet ds = this.Query(sql);//查詢出此次的資料 #region 總頁數、總筆數文字顯示處理 int totalRows = ds.Tables[0].Rows.Count;//總筆數 li_totalRows.Text = totalRows.ToString(); //總頁數(自己算) int totalPages = (totalRows / pageSize);//取商數(總筆數除以每頁顯示幾筆,得到總頁數) if (totalRows % pageSize > 0)//若餘數大於0,不整除的話,總頁數要加1,道理如同小學數學題 多出來的學生也要多叫一部遊覽車送去郊遊是一樣的 { totalPages++; } //int totalPages = pds.PageCount; //防呆寫法 if (currentPage > totalPages) currentPage = totalPages; if (currentPage < 1) currentPage = 1; //ListView顯示分頁後的資料,並做DataBind(),這次的currentPage經過防呆後,應該是正確的值 /*lv_showData還沒有傳進來,先註解*/ /*System.Web.UI.WebControls.PagedDataSource pds = DBUtility.pageData(ds, pageSize, currentPage, lv_showData); */ dl_currentPage.Items.Clear(); for (int i = 1; i <= totalPages; i++) { dl_currentPage.Items.Add(i.ToString()); } //目前第幾頁的下拉選單選擇值 dl_currentPage.SelectedValue = currentPage.ToString(); //每頁顯示幾筆的下拉選單選擇值 dl_pageSize.SelectedValue = pageSize.ToString(); //第一頁和最後一頁時,第一頁、上一頁、下一頁、最末頁按鈕Enabled的處理防呆 if (currentPage == 1)//目前在第一頁 { lnkFirstPage.Enabled = false; lnkPrePage.Enabled = false; } else { lnkFirstPage.Enabled = true; lnkPrePage.Enabled = true; } if (currentPage == totalPages)//目前在最後一頁 { lnkLastPage.Enabled = false; lnkNextPage.Enabled = false; } else { lnkLastPage.Enabled = true; lnkNextPage.Enabled = true; } #endregion } #endregion /// <summary> /// 傳入SQL查詢語句,回傳DataSet /// </summary> /// <param name="sql"></param> /// <returns></returns> private DataSet Query(string sql) { DataSet ds = new DataSet(); using (SqlConnection conn = new SqlConnection(this.connStr)) { SqlDataAdapter da = new SqlDataAdapter(sql, conn); da.Fill(ds); } return ds; } //第一頁Click protected void lnkFirstPage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = "1";//到第一頁 this.btnToPage_Click(null, null);//跳頁事件 } //上一頁Click protected void lnkPrePage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = Convert.ToInt32(dl_currentPage.SelectedValue) - 1 + ""; this.btnToPage_Click(null, null);//跳頁事件 } //下一頁Click protected void lnkNextPage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = Convert.ToInt32(dl_currentPage.SelectedValue) + 1 + ""; this.btnToPage_Click(null, null);//跳頁事件 } //最後一頁 protected void lnkLastPage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = dl_currentPage.Items[dl_currentPage.Items.Count - 1].Value; this.btnToPage_Click(null, null);//跳頁事件 } #region 跳頁事件postback的處理 protected void btnToPage_Click(object sender, EventArgs e) { #region 防呆,當查詢無資料時,dl_currentPage.SelectedValue會空字串,為了避免再按一次搜尋或再次postback時,程式掛掉,加入以下判斷 int currentPage = 1; if (dl_currentPage.SelectedValue == "") { currentPage = 1; } else { currentPage = Convert.ToInt32(dl_currentPage.SelectedValue); } /*每次跳頁postback就要經過queryData方法,SQL語句要經過篩選*/ /*先註解*/ //this.queryData(currentPage, Convert.ToInt32(dl_pageSize.SelectedValue)); #endregion } #endregion }
要先註解的地方:
/*這時候ListView還沒傳進來*/ /*System.Web.UI.WebControls.PagedDataSource pds = DBUtility.pageData(ds, pageSize, currentPage, lv_showData); */ #region 跳頁事件postback的處理 protected void btnToPage_Click(object sender, EventArgs e) { #region 防呆,當查詢無資料時,dl_currentPage.SelectedValue會空字串,為了避免再按一次搜尋或再次postback時,程式掛掉,加入以下判斷 int currentPage = 1; if (dl_currentPage.SelectedValue == "") { currentPage = 1; } else { currentPage = Convert.ToInt32(dl_currentPage.SelectedValue); } /*每次跳頁postback就要經過queryData方法*/ /*queryData方法為經過查詢條件篩選過的SQL語句,因為每個畫面的查詢條件不一樣 * 故queryData方法內的篩選條件也不一樣,不用把queryData方法也搬移到WebUserControl*/ //this.queryData(currentPage, Convert.ToInt32(dl_pageSize.SelectedValue)); #endregion } #endregion
為了讓此WebUserControl能夠接到從 *.aspx傳過來的值
所以要再改寫一下,大概要傳進來的值有ListView控制項、sql語句,這兩個要從Session中提取
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; /*要引用以下三個命名空間*/ using System.Data; using System.Data.SqlClient; using System.Web.Configuration; //要傳給此WebUserControl的值 //Session["sql"]和Session["DataBoundControl"] public partial class pageListViewOrGridView : System.Web.UI.UserControl { /*連線字串*/ string connStr = WebConfigurationManager.ConnectionStrings["connStr"].ConnectionString; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack)//Get Method要做的事 { int currentPage = 1;//預設目前第一頁 int pageSize = 5;//預設每頁顯示5筆 if (Session["sql"]!=null) { string sql = (string)Session["sql"]; this.showData(currentPage, pageSize, sql); } } } #region 分頁資料,總筆數、總頁數文字顯示處理 protected void showData(int currentPage, int pageSize, string sql) { DataSet ds = this.Query(sql);//查詢出此次的資料 #region 總頁數、總筆數文字顯示處理 int totalRows = ds.Tables[0].Rows.Count;//總筆數 li_totalRows.Text = totalRows.ToString(); //總頁數(自己算) int totalPages = (totalRows / pageSize);//取商數(總筆數除以每頁顯示幾筆,得到總頁數) if (totalRows % pageSize > 0)//若餘數大於0,不整除的話,總頁數要加1,道理如同小學數學題 多出來的學生也要多叫一部遊覽車送去郊遊是一樣的 { totalPages++; } //int totalPages = pds.PageCount; //防呆寫法 if (currentPage > totalPages) currentPage = totalPages; if (currentPage < 1) currentPage = 1; //從Session取得ListView控制項 DataBoundControl dbc = this.getDataBoundControlFromSession(); //ListView顯示分頁後的資料,並做DataBind(),currentPage經過防呆後,應該是正確的值 System.Web.UI.WebControls.PagedDataSource pds = DBUtility.pageData(ds, pageSize, currentPage, dbc); dl_currentPage.Items.Clear(); for (int i = 1; i <= totalPages; i++) { dl_currentPage.Items.Add(i.ToString()); } //目前第幾頁的下拉選單選擇值 dl_currentPage.SelectedValue = currentPage.ToString(); //每頁顯示幾筆的下拉選單選擇值 dl_pageSize.SelectedValue = pageSize.ToString(); //第一頁和最後一頁時,第一頁、上一頁、下一頁、最末頁按鈕Enabled的處理防呆 if (currentPage == 1)//目前在第一頁 { lnkFirstPage.Enabled = false; lnkPrePage.Enabled = false; } else { lnkFirstPage.Enabled = true; lnkPrePage.Enabled = true; } if (currentPage == totalPages)//目前在最後一頁 { lnkLastPage.Enabled = false; lnkNextPage.Enabled = false; } else { lnkLastPage.Enabled = true; lnkNextPage.Enabled = true; } #endregion } #endregion /// <summary> /// 傳入SQL查詢語句,回傳DataSet /// </summary> /// <param name="sql"></param> /// <returns></returns> private DataSet Query(string sql) { DataSet ds = new DataSet(); using (SqlConnection conn = new SqlConnection(this.connStr)) { SqlDataAdapter da = new SqlDataAdapter(sql, conn); da.Fill(ds); } return ds; } /// <summary> /// 從Session中抓出ListView或GridView /// </summary> /// <returns></returns> private DataBoundControl getDataBoundControlFromSession() { DataBoundControl dbc = null; if (Session["DataBoundControl"] is ListView) { dbc = (ListView)Session["DataBoundControl"]; } else if (Session["DataBoundControl"] is GridView) { dbc = (GridView)Session["DataBoundControl"]; } return dbc; } //第一頁Click protected void lnkFirstPage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = "1";//到第一頁 this.btnToPage_Click(null, null);//跳頁事件 } //上一頁Click protected void lnkPrePage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = Convert.ToInt32(dl_currentPage.SelectedValue) - 1 + ""; this.btnToPage_Click(null, null);//跳頁事件 } //下一頁Click protected void lnkNextPage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = Convert.ToInt32(dl_currentPage.SelectedValue) + 1 + ""; this.btnToPage_Click(null, null);//跳頁事件 } //最後一頁 protected void lnkLastPage_Click(object sender, EventArgs e) { dl_currentPage.SelectedValue = dl_currentPage.Items[dl_currentPage.Items.Count - 1].Value; this.btnToPage_Click(null, null);//跳頁事件 } #region 跳頁事件postback的處理 /*要改成public,因為其他.aspx畫面經過自己的queryData方法後,要呼叫此btnToPage_Click方法*/ public void btnToPage_Click(object sender, EventArgs e) { #region 防呆,當查詢無資料時,dl_currentPage.SelectedValue會空字串,為了避免再按一次搜尋或再次postback時,程式掛掉,加入以下判斷 //先抓出此WebUserControl上的currentPage和pageSize int currentPage = 1; if (dl_currentPage.SelectedValue == "") { currentPage = 1; } else { currentPage = Convert.ToInt32(dl_currentPage.SelectedValue); } int pageSize = Convert.ToInt32(dl_pageSize.SelectedValue); /*queryData方法為經過查詢條件篩選過的SQL語句,因為每個畫面的查詢條件不一樣 * 故queryData方法內的篩選條件也不一樣,不用把queryData方法也搬移到此WebUserControl*/ /*這時候的Session["sql"]可能是篩選過的SQL語句*/ if (Session["sql"] != null) { string sql = (string)Session["sql"]; this.showData(currentPage, pageSize, sql); } #endregion } #endregion }
接著回到.aspx,把畫面上的東西也稍作整理
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PagedDataSourceDemo.aspx.cs" Inherits="PagedDataSourceDemo" %> <%@ Register TagPrefix="include" TagName="pageData" Src="~/pageListViewOrGridView.ascx" %> <!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> </head> <body> <form id="form1" runat="server"> <%--查詢條件的下拉選單,OnSelectedIndexChanged事件要改--%> <asp:DropDownList runat="server" ID="ddl_SelectID" AutoPostBack="true" OnSelectedIndexChanged="queryData"> <asp:ListItem Text="請選擇" Value="-1" /> <asp:ListItem Text="5" Value="5" /> <asp:ListItem Text="10" Value="10" /> </asp:DropDownList> <%--表格式ListView--%> <asp:ListView ID="lv_showData" runat="server"> <ItemTemplate> <tr> <td> <asp:Literal ID="idLiteral" runat="server" Text='<%# Eval("id") %>' /> </td> <td> <asp:Literal ID="titleLiteral" runat="server" Text='<%# Eval("title") %>' /> </td> </tr> </ItemTemplate> <LayoutTemplate> <table id="itemPlaceholderContainer" runat="server" align="center" cellpadding="0" cellspacing="0" border="1" style="border-style: solid;"> <tr> <th runat="server"> id </th> <th runat="server"> title </th> </tr> <tr id="itemPlaceholder" runat="server"> </tr> </table> </LayoutTemplate> </asp:ListView> <%--分頁區塊--%> <include:pageData ID="pageData1" runat="server" /> </form> </body> </html>
.aspx的Code-Behind
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; public partial class PagedDataSourceDemo : System.Web.UI.Page { string sqlSelect = " Select * from tb_data Where 1=1 "; string sqlOrderBy = " Order by id ASC"; protected void Page_Load(object sender, EventArgs e) { //不管是不是postback,都要把ListView控制項存在Session裡 Session["DataBoundControl"] = this.lv_showData; if (!IsPostBack)//Get Method要做的動作 { //撈全部的資料 Session["sql"] = this.sqlSelect + this.sqlOrderBy; //.aspx的Page_Load事件執行完後才會去執行.ascx的Page_Load事件 //之後的資料呈現就交給 分頁WebUserControl的Page_Load事件處理 } } //下拉選單更動或假設按了搜尋按鈕都要經過此SQL語法 protected void queryData(object sender,EventArgs e) { string sql = this.sqlSelect; if (ddl_SelectID.SelectedIndex>0)//有選擇 { sql += " And id > '"+ddl_SelectID.SelectedValue+"'"; } //排序 sql += this.sqlOrderBy; //篩選過的SQL語句儲存在Session,讓.ascx可以讀得到 Session["sql"] = sql; //呼叫跳頁方法 ((pageListViewOrGridView)this.FindControl("pageData1")).btnToPage_Click(null, null); } }
執行結果和上一個範例是一樣的::[ASP.net WebForm] 使用PagedDataSource物件實現手寫分頁 (適合初學者)
所以現在有任何的 *.aspx要套用此分頁WebUserControl的話
記得追加修改以下粗體字部份
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PagedDataSourceDemo.aspx.cs" Inherits="PagedDataSourceDemo" %> <%@ Register TagPrefix="include" TagName="pageData" Src="~/pageListViewOrGridView.ascx" %> <!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> </head> <body> <form id="form1" runat="server"> <%--查詢條件的下拉選單,OnSelectedIndexChanged事件要改--%> <asp:DropDownList runat="server" ID="ddl_SelectID" AutoPostBack="true" OnSelectedIndexChanged="queryData"> <asp:ListItem Text="請選擇" Value="-1" /> <asp:ListItem Text="5" Value="5" /> <asp:ListItem Text="10" Value="10" /> </asp:DropDownList> <%--表格式ListView--%> <asp:ListView ID="lv_showData" runat="server"> <ItemTemplate> <tr> <td> <asp:Literal ID="idLiteral" runat="server" Text='<%# Eval("id") %>' /> </td> <td> <asp:Literal ID="titleLiteral" runat="server" Text='<%# Eval("title") %>' /> </td> </tr> </ItemTemplate> <LayoutTemplate> <table id="itemPlaceholderContainer" runat="server" align="center" cellpadding="0" cellspacing="0" border="1" style="border-style: solid;"> <tr> <th runat="server"> id </th> <th runat="server"> title </th> </tr> <tr id="itemPlaceholder" runat="server"> </tr> </table> </LayoutTemplate> </asp:ListView> <%--分頁區塊--%> <include:pageData ID="pageData1" runat="server" /> </form> </body> </html>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; public partial class PagedDataSourceDemo : System.Web.UI.Page { string sqlSelect = " Select * from tb_data Where 1=1 "; string sqlOrderBy = " Order by id ASC"; protected void Page_Load(object sender, EventArgs e) { //不管是不是postback,都要把ListView控制項存在Session裡 Session["DataBoundControl"] = this.lv_showData; if (!IsPostBack)//Get Method要做的動作 { //撈全部的資料 Session["sql"] = this.sqlSelect + this.sqlOrderBy; //.aspx的Page_Load事件執行完後才會去執行.ascx的Page_Load事件 //之後的資料呈現就交給 分頁WebUserControl的Page_Load事件處理 } } //下拉選單更動或假設按了搜尋按鈕都要經過此SQL語法 protected void queryData(object sender, EventArgs e) { string sql = this.sqlSelect; if (ddl_SelectID.SelectedIndex > 0)//有選擇 { sql += " And id > '" + ddl_SelectID.SelectedValue + "'"; } //排序 sql += this.sqlOrderBy; //篩選過的SQL語句儲存在Session,讓.ascx可以讀得到 Session["sql"] = sql; //呼叫跳頁方法 ((pageListViewOrGridView)this.FindControl("pageData1")).btnToPage_Click(null, null); } }
衍伸閱讀其他部落客文章: