當我們將資料庫資料取出後,若要以分頁的方式顯示在頁面上,可以使用 ListView 搭配 DataPager 來實作分頁功能,但是若沒有實作資料來源分頁,那麼資料讀取動作會是將所有符合查詢條件的資料從資料庫全部取出後丟給 ListView,再由控制項自行處理要顯示的資料,因為必須將不需顯示的資料也一併從資料庫讀取出來,此種方式會造成資料庫沉重的負擔,在這裡來介紹搭配 ObjectDataSource 的方式來實作資料來源分頁。
先來張執行結果擷圖:
![]()
先建立 ListView 及 DataPager 物件,來看一下 ASPX 的內容:
02 | <asp:ListView ID="ListView1" ItemPlaceholderID="phContent" runat="server"> |
04 | <table width="400px" border="0" cellpadding="4" cellspacing="1" bgcolor="#999999" class="font_02"> |
05 | <tr style="background:#CCCCCC"> |
06 | <td width="40%">購買日期</td> |
07 | <td width="30%">購買商品</td> |
08 | <td width="30%">購買數量</td> |
10 | <asp:PlaceHolder ID="phContent" runat="server"></asp:PlaceHolder> |
14 | <tr style="background:#FFFFFF"> |
15 | <td width="40%"><%#DataBinder.Eval(Container, "DataItem.Date") %></td> |
16 | <td width="30%"><%#DataBinder.Eval(Container, "DataItem.Name") %></td> |
17 | <td width="30%"><%#DataBinder.Eval(Container, "DataItem.Qty") %></td> |
22 | <table width="400px" border="0" class="pager"> |
24 | <asp:DataPager ID="DataPager1" PagedControlID="ListView1" runat="server"> |
26 | <asp:NextPreviousPagerField ButtonCssClass="font_01" ShowNextPageButton="False" PreviousPageText="上一頁" /> |
27 | <asp:NumericPagerField ButtonCount="10" NumericButtonCssClass="font_01" |
28 | NextPreviousButtonCssClass="font_01" CurrentPageLabelCssClass="font_03" /> |
29 | <asp:NextPreviousPagerField ButtonCssClass="font_01" ShowPreviousPageButton="False" NextPageText="下一頁" /> |
設定 ListView 及頁碼要顯示的內容及格式,在資料繫結的欄位設定上,我是使用 DataBinder.Eval(Container, "DateItem.Name") 的方式繫結,因為此方式的執行效能較高,參考文章在此。
而 ObjectDataSource 的設定是實作這資料來源分頁很重要的地方,程式碼如下:
01 | //動態產生 ObjectDataSource 物件 |
02 | private ObjectDataSource odsList = new ObjectDataSource(); |
04 | protected void Page_Init(object sender, EventArgs e) |
06 | //將 ObjectDataSource 名稱命名為 odsList |
07 | odsList.ID = "odsList"; |
09 | odsList.EnablePaging = true; |
11 | odsList.SelectMethod = "QryData"; |
13 | odsList.SelectCountMethod = "QryData_GetRowCount"; |
14 | //指出 SelectMethod、SelectCountMethod 方法要去哪個 Class 中調用 |
15 | odsList.TypeName = "MyFunc"; |
16 | //呼叫 SelectMethod 時傳入的參數--每頁開始的筆數(由0算起) |
17 | odsList.StartRowIndexParameterName = "StartRowIndex"; |
18 | //呼叫 SelectMethod 時傳入的參數--每頁顯示的筆數(會參考 DataPager 中 PageSize 的設定) |
19 | odsList.MaximumRowsParameterName = "MaximumRows"; |
21 | //將 ObjectDataSource 加入至頁面中 |
22 | Page.Form.Controls.Add(odsList); |
25 | DataPager1.PageSize = MyFunc.cPageSize; |
27 | //設定 ListView 在取資料時要參考的資料來源 |
28 | ListView1.DataSourceID = odsList.ID; |
32 | protected void Page_PreLoad(object sender, EventArgs e) |
34 | //odsList.SelectParameters.Clear(); |
35 | //設定查詢起迄日期 (名稱須與方法中接收的參數名稱相同) |
36 | //odsList.SelectParameters.Add("QryStartDate", "2009/7/1"); |
37 | //odsList.SelectParameters.Add("QryEndDate", "2009/7/11"); |
我在每一行程式上面都有註解其作用,主要就是靠這裡的設定在運作的,像是指定要讀取資料時要至哪個地方(TypeName) 執行什麼程式(SelectMethod、SelectCountMethod),若要傳入自定條件參數,可使用第 35 行的 SelectParametrs.Add() 方法。
以上面的設定來說,我的 MyFunc 類別會定義如下:
03 | public const int cPageSize = 5; //每頁顯示筆數 |
05 | /// <summary>查詢資料(只取出顯示頁面所需的筆數資料)</summary> |
06 | public DataTable QryData(int StartRowIndex, int MaximumRows) |
11 | /// <summary>取得資料總筆數</summary> |
13 | /// 註:此方法會在 QryData 呼叫完後,才被呼叫 |
15 | public int QryData_GetRowCount() |
17 | //此處撰寫程式碼取得符合條件資料之總筆數並傳回 |
QryData() 接收了 2 個傳入的參數,此參數名稱須對應至 ObjectDataSource 中屬性 StartRowIndexParameterName、MaximumRowsParameterName 設定的名稱相同。若要在呼叫方法時一併傳入其他參數,例如查詢日期區間條件,那麼 QryData() 及 QryData_GetRowCount() 定義會修改成如下:
01 | /// <summary>查詢資料(只取出顯示頁面所需的筆數資料)</summary> |
02 | /// <param name="StartRowIndex">每頁開始的筆數(由0算起)</param> |
03 | /// <param name="MaximumRows">每頁顯示的筆數</param> |
04 | /// <param name="QryStartDate">查詢日期起日</param> |
05 | /// <param name="QryEndDate">查詢日期迄日</param> |
06 | public DataTable QryData(int StartRowIndex, int MaximumRows, string QryStartDate, string QryEndDate) |
11 | public int QryData_GetRowCount(string QryStartDate, string QryEndDate) |
13 | //此處撰寫程式碼取得符合條件資料之總筆數並傳回 |
在呼叫前就要設定 QryStartDate 跟 QryEndDate 的值,方法如下:
1 | odsList.SelectParameters.Clear(); |
2 | odsList.SelectParameters.Add("QryStartDate", "2009/7/1"); |
3 | odsList.SelectParameters.Add("QryEndDate", "2009/7/11"); |
如此就可享用資料來源分頁的效能提升了。
在設定 ObjectDataSource 的 TypeName 時有 1 個要注意的地方,若專案類型是 WebSite,則此類別可建立在 App_Code 底下,此時 TypeName 設定為 MyFunc 即可。
若專案類型是 Project,那麼在設定 TypeName 時須包含專案的 Namespace,例如 odsList.TypeName = "MyProject.MyFunc",其中 MyProject 就是專案的命名空間,若發生找不到類別名稱時會出現類似如下的訊息:
英文訊息:
The type specified in the TypeName property of ObjectDataSource 'odsList' could not be found.
中文訊息:
找不到 ObjectDataSource 'odsList' 的 TypeName 屬性所指定的型別。
這裡有寫好的範例程式可下載回去試試看:20090711_DataPagerSample.zip
參考資料: