接著上篇介紹,上篇已經(jīng)通過DropDownList簡(jiǎn)單實(shí)現(xiàn)了排序的功能,下面讓我們看看帶有分頁的排序該怎么做。
第五步: 為使用默認(rèn)分頁的DataList添加排序的支持
打開PagingSortingDataListRepeater文件夾里的SortingWithDefaultPaging.aspx和Paging.aspx 頁。在Paging.aspx 頁里查看源文件。將圖8里選擇的文本復(fù)制下來,然后粘貼到SortingWithDefaultPaging.aspx 頁里的asp:Content> 標(biāo)簽內(nèi)。
圖 8: 復(fù)制粘貼代碼
然后將Paging.aspx頁后臺(tái)代碼里的屬性和方法也粘貼到SortingWithDefaultPaging.aspx頁后臺(tái)代碼里。現(xiàn)在瀏覽SortingWithDefaultPaging.aspx頁,它現(xiàn)在應(yīng)該有和Paging.aspx頁一樣的外觀和功能。
在ProductsBLL 里添加默認(rèn)的分頁和排序方法
前面一章里我們?cè)赑roductsBLL類里創(chuàng)建了一個(gè)GetProductsAsPagedDataSource(pageIndex, pageSize)方法,它返回一個(gè)PagedDataSource對(duì)象。這個(gè)對(duì)象通過BLL的GetProducts()方法獲取所有的product,然而綁定到DataList的只是那些和輸入?yún)?shù)pageIndex 和 pageSize 相關(guān)的記錄。
本章前面我們已經(jīng)通過在ObjectDataSource的 Selecting event handler里指定sort expression來添加了排序功能。當(dāng)ObjectDataSource返回可排序?qū)ο髸r(shí)這個(gè)方法運(yùn)轉(zhuǎn)的很好,比如GetProducts()方法返回的ProductsDataTable。然而GetProductsAsPagedDataSource方法返回的PagedDataSource對(duì)象并不支持對(duì)它內(nèi)部數(shù)據(jù)的排序,因此我們需要在將數(shù)據(jù)放入PagedDataSource前對(duì)GetProducts()方法返回的記錄進(jìn)行排序。
在ProductsBLL類里建一個(gè)GetProductsSortedAsPagedDataSource(sortExpression, pageIndex, pageSize)方法。指定GetProducts() 方法返回的ProductsDataTable的default DataTableView的排序?qū)傩浴?/p>
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public PagedDataSource GetProductsSortedAsPagedDataSource
(string sortExpression, int pageIndex, int pageSize)
{
// Get ALL of the products
Northwind.ProductsDataTable products = GetProducts();
// Sort the products
products.DefaultView.Sort = sortExpression;
// Limit the results through a PagedDataSource
PagedDataSource pagedData = new PagedDataSource();
pagedData.DataSource = products.DefaultView;
pagedData.AllowPaging = true;
pagedData.CurrentPageIndex = pageIndex;
pagedData.PageSize = pageSize;
return pagedData;
}
GetProductsSortedAsPagedDataSource方法和前面一章里的GetProductsAsPagedDataSource方法有一點(diǎn)不一樣。GetProductsSortedAsPagedDataSource多了一個(gè)sortExpression參數(shù),將它的值賦給ProductDataTable的 DefaultView的Sort屬性。并將ProductDataTable的DefaultView賦給PagedDataSource對(duì)象的DataSource。
調(diào)用 GetProductsSortedAsPagedDataSource 方法并指定輸入?yún)?shù)SortExpression的值
完成這些后,下一步需要提供參數(shù)值。SortingWithDefaultPaging.aspx頁的ObjectDataSource現(xiàn)在被配置用來調(diào)用GetProductsAsPagedDataSource方法并通過兩個(gè)QueryStringParameters來傳遞參數(shù),這些參數(shù)在SelectParameters集合里已經(jīng)指定了。這兩個(gè)QueryStringParameters參數(shù)表示GetProductsAsPagedDataSource方法的pageIndex 和 pageSize 參數(shù)從querystring里獲取。
修改ObjectDataSource的SelectMethod屬性,讓它調(diào)用GetProductsSortedAsPagedDataSource方法。然后添加一個(gè)新的QueryStringParameter來讓sortExpression 參數(shù)通過querystring的sortExpression字段獲取。將QueryStringParameter的默認(rèn)值設(shè)為“ProductName”。
現(xiàn)在ObjectDataSource的聲明標(biāo)記語言看起來應(yīng)該和下面差不多:
asp:ObjectDataSource ID="ProductsDefaultPagingDataSource"
OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
SelectMethod="GetProductsSortedAsPagedDataSource"
OnSelected="ProductsDefaultPagingDataSource_Selected" runat="server">
SelectParameters>
asp:QueryStringParameter DefaultValue="ProductName"
Name="sortExpression" QueryStringField="sortExpression"
Type="String" />
asp:QueryStringParameter DefaultValue="0" Name="pageIndex"
QueryStringField="pageIndex" Type="Int32" />
asp:QueryStringParameter DefaultValue="4" Name="pageSize"
QueryStringField="pageSize" Type="Int32" />
/SelectParameters>
/asp:ObjectDataSource>
現(xiàn)在SortingWithDefaultPaging.aspx頁會(huì)按照product name的字母順序排序。見圖9。這是因?yàn)镚etProductsSortedAsPagedDataSource方法的sortExpression 參數(shù)的默認(rèn)值為“ProductName”。
圖 9: 默認(rèn)的按照 ProductName 排序
如果你手動(dòng)添加一個(gè)sortExpression querystring字段–比如SortingWithDefaultPaging.aspx?sortExpression=CategoryName –那么結(jié)果會(huì)以指定的sortExpression來排序。然而在轉(zhuǎn)到另外一個(gè)頁時(shí)這個(gè)sortExpression參數(shù)并沒有包含在querystring里。實(shí)際上當(dāng)點(diǎn)上或者下一頁時(shí)我們會(huì)返回Paging.aspx。而且當(dāng)前并沒有排序界面。用戶可以改變數(shù)據(jù)排序的唯一方法是直接操作querystring。
創(chuàng)建排序界面
我們首先要修改RedirectUser方法來將用戶重定向到SortingWithDefaultPaging.aspx頁(而不是Paging.aspx),并將sortExpression的值包含到querystring里。我們還應(yīng)該添加一個(gè)只讀的SortExpression屬性。這個(gè)屬性和前面一章里創(chuàng)建的PageIndex 和 PageSize屬性相似,在sortExpression querystring字段存在時(shí)返回它的值,否則的話使用默認(rèn)值“ProductName”。
現(xiàn)在的RedirectUser方法只接收一個(gè)參數(shù)–顯示的頁的index。然而可能有些時(shí)候我們需要使用排序表達(dá)式將用戶重定向到特定數(shù)據(jù)的頁。我們將馬上來為這個(gè)頁創(chuàng)建排序界面,它將包含一些button來為指定的列排序。當(dāng)其中一個(gè)button被點(diǎn)擊時(shí),我們需要傳入合適的排序表達(dá)式的值來重定向用戶。為了提供這個(gè)功能,創(chuàng)建兩個(gè)RedirectUser方法。第一個(gè)接收page的index,第二個(gè)接收page index和sort expression(排序表達(dá)式)。
private string SortExpression
{
get
{
if (!string.IsNullOrEmpty(Request.QueryString["sortExpression"]))
return Request.QueryString["sortExpression"];
else
return "ProductName";
}
}
private void RedirectUser(int sendUserToPageIndex)
{
// Use the SortExpression property to get the sort expression
// from the querystring
RedirectUser(sendUserToPageIndex, SortExpression);
}
private void RedirectUser(int sendUserToPageIndex, string sendUserSortingBy)
{
// Send the user to the requested page with the requested sort expression
Response.Redirect(string.Format(
"SortingWithDefaultPaging.aspx?pageIndex={0}pageSize={1}sortExpression={2}",
sendUserToPageIndex, PageSize, sendUserSortingBy));
}
本章的第一個(gè)例子里,我們使用DropDownList來創(chuàng)建了一個(gè)排序界面。我們將在這個(gè)例子里使用3個(gè)button(它們位于DataList上方)–一個(gè)表示為ProductName排序,一個(gè)為CategoryName,一個(gè)為SupplierName。添加三個(gè)button并設(shè)置它們的ID和Text。
p>
asp:Button runat="server" id="SortByProductName"
Text="Sort by Product Name" />
asp:Button runat="server" id="SortByCategoryName"
Text="Sort by Category" />
asp:Button runat="server" id="SortBySupplierName"
Text="Sort by Supplier" />
/p>
然后為每個(gè)button創(chuàng)建一個(gè)Click event handler。這個(gè)事件處理將調(diào)用RedirectUser方法,并使用合適的排序表達(dá)式將用戶返回到第一頁。
protected void SortByProductName_Click(object sender, EventArgs e)
{
// Sort by ProductName
RedirectUser(0, "ProductName");
}
protected void SortByCategoryName_Click(object sender, EventArgs e)
{
// Sort by CategoryName
RedirectUser(0, "CategoryName");
}
protected void SortBySupplierName_Click(object sender, EventArgs e)
{
// Sort by SupplierName
RedirectUser(0, "SupplierName");
}
第一次瀏覽該頁時(shí),數(shù)據(jù)將按照product name的字母順序排序(見圖9)。點(diǎn)Next button來瀏覽第二頁,然后點(diǎn)“Sort by Category” button。這樣將讓頁返回到第一頁,并按照category name來排序,見圖10。同樣的,點(diǎn)“Sort by Supplier” button會(huì)將數(shù)據(jù)按照supplier排序,并返回到第一頁。當(dāng)數(shù)據(jù)分頁時(shí)排序的選擇會(huì)被記下來。圖11是按照category排序并瀏覽第十三頁的樣子。
圖 10: Products 按照Category排序
圖 11: 分頁時(shí)會(huì)記下Sort Expression
第六步: Repeater的自定義分頁
第五步里的DataList示例使用默認(rèn)的分頁技術(shù)。當(dāng)大數(shù)據(jù)量時(shí),我們需要使用自定義分頁?;氐紼fficiently Paging Through Large Amounts of Data 和 Sorting Custom Paged Data 里,我們學(xué)習(xí)了默認(rèn)和自定義這兩種分頁方式的不同,并在BLL里為自定義分頁和對(duì)自定義分頁數(shù)據(jù)的排序創(chuàng)建了方法。在這兩章里我們?cè)赑roductsBLL里添加了下面三個(gè)方法:
GetProductsPaged(startRowIndex, maximumRows) – 返回從startRowIndex開始并不超過maximumRows 的特定記錄集。
GetProductsPagedAndSorted(sortExpression, startRowIndex, maximumRows) – 根據(jù)指定的sortExpression 返回特定記錄集。
TotalNumberOfProducts() – 提供Products 表的總記錄數(shù)。
這些方法可以用來在DataList或Repeater進(jìn)行高效的分頁并排序。我們首先創(chuàng)建一個(gè)支持自定義分頁的Repeater。然后再添加排序支持。打開PagingSortingDataListRepeater文件夾下的SortingWithCustomPaging.aspx頁,添加一個(gè)Repeater,將ID設(shè)為Products。從智能標(biāo)簽里創(chuàng)建一個(gè)名為ProductsDataSource的ObjectDataSource。使用ProductsBLL類的GetProductsPaged方法來配置它的select標(biāo)簽。
圖 12: 配置 ObjectDataSource
在UPDATE, INSERT, DELETE標(biāo)簽里選擇“(None)”,點(diǎn)下一步?,F(xiàn)在我們需要為GetProductsPaged方法的startRowIndex 和 maximumRows 參數(shù)選擇源。實(shí)際上這里不需要配置。這兩個(gè)參數(shù)的值會(huì)在ObjectDataSource的Selecting event handler里通過Arguments屬性來指定,就好象我們?cè)诒菊碌牡谝粋€(gè)例子里指定sortExpression 一樣。因此,在參數(shù)源的下拉列表里選擇“None”。
圖 13:將參數(shù)源設(shè)為 “None”
注意:不要將ObjectDataSource的EnablePaging屬性設(shè)為true。這樣會(huì)讓ObjectDataSource自動(dòng)的將它的startRowIndex 和 maximumRows 參數(shù)包含在SelectMethod的已經(jīng)存在的參數(shù)列表里。EnablePaging屬性在將自定義分頁數(shù)據(jù)綁定到GridView, DetailsView, FormView時(shí)才有用。由于我們是為DataList 和Repeater手動(dòng)添加分頁支持,因此將它們?cè)O(shè)為false(默認(rèn)的),我們將在ASP.NET頁里直接實(shí)現(xiàn)這些功能。
最后,定義Repeater的ItemTemplate,讓它只顯示product'的name, category, supplier。完成這些后,Repeater和ObjectDataSource的聲明語言看起來應(yīng)該和下面差不多:
asp:Repeater ID="Products" runat="server" DataSourceID="ProductsDataSource"
EnableViewState="False">
ItemTemplate>
h4>asp:Label ID="ProductNameLabel" runat="server"
Text='%# Eval("ProductName") %>'>/asp:Label>/h4>
Category:
asp:Label ID="CategoryNameLabel" runat="server"
Text='%# Eval("CategoryName") %>'>/asp:Label>br />
Supplier:
asp:Label ID="SupplierNameLabel" runat="server"
Text='%# Eval("SupplierName") %>'>/asp:Label>br />
br />
br />
/ItemTemplate>
/asp:Repeater>
asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsPaged" TypeName="ProductsBLL">
SelectParameters>
asp:Parameter Name="startRowIndex" Type="Int32" />
asp:Parameter Name="maximumRows" Type="Int32" />
/SelectParameters>
/asp:ObjectDataSource>
現(xiàn)在瀏覽該頁,注意沒有返回任何記錄。這是因?yàn)槲覀冞€沒有指定startRowIndex 和 maximumRows 參數(shù)的值。為了指定這些值,為ObjectDataSource的Selecting event創(chuàng)建一個(gè)event handler,并將參數(shù)值硬編碼的設(shè)置為0和5。
protected void ProductsDataSource_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
e.InputParameters["startRowIndex"] = 0;
e.InputParameters["maximumRows"] = 5;
}
現(xiàn)在瀏覽頁面時(shí)會(huì)顯示前5條product記錄。
圖 14: 顯示前5條product
注意:圖14列出的products以product name排序是因?yàn)樽远x分頁使用的GetProductsPaged存儲(chǔ)過程返回的結(jié)果是以ProductName排序。
為了讓用戶可以翻頁,我們需要在postback過程中記下start row index 和 maximum rows。在默認(rèn)分頁的例子里我們用querystring來保存這些值。這個(gè)例子里我們將使用view state。創(chuàng)建下面兩個(gè)屬性:
private int StartRowIndex
{
get
{
object o = ViewState["StartRowIndex"];
if (o == null)
return 0;
else
return (int)o;
}
set
{
ViewState["StartRowIndex"] = value;
}
}
private int MaximumRows
{
get
{
object o = ViewState["MaximumRows"];
if (o == null)
return 5;
else
return (int)o;
}
set
{
ViewState["MaximumRows"] = value;
}
}
然后更新Selecting event handler的代碼,使用StartRowIndex 和 MaximumRows屬性代替硬編碼的0和5。
e.InputParameters["startRowIndex"] = StartRowIndex;
e.InputParameters["maximumRows"] = MaximumRows;
現(xiàn)在我們的頁仍然只顯示5條記錄。然而完成這些屬性后,我們已經(jīng)可以創(chuàng)建分頁界面了。
添加分頁界面
我們還是使用和默認(rèn)分頁例子里一樣的First, Previous, Next, Last分頁界面,并包含顯示當(dāng)前是哪頁和總頁數(shù)的label。在Repeater下面添加4個(gè)button和1一個(gè)label。
p>
asp:Button runat="server" ID="FirstPage" Text=" First" />
asp:Button runat="server" ID="PrevPage" Text=" Prev" />
asp:Button runat="server" ID="NextPage" Text="Next >" />
asp:Button runat="server" ID="LastPage" Text="Last >>" />
/p>
p>
asp:Label runat="server" ID="CurrentPageNumber">/asp:Label>
/p>
然后為4個(gè)button創(chuàng)建Click event handlers。當(dāng)其中一個(gè)button被點(diǎn)時(shí),我們需要修改StartRowIndex并將數(shù)據(jù)重新綁定到Repeater。First, Previous, 和 Next button的代碼都非常簡(jiǎn)單,但是對(duì)Last button來說,我們?nèi)绾闻袛嘧詈笠豁摂?shù)據(jù)的start row index?為了計(jì)算出這個(gè)index–和判斷Next 和 Last button是否應(yīng)該enabled一樣–我們需要知道分頁數(shù)據(jù)的總數(shù)。我們可以調(diào)用ProductsBLL類的TotalNumberOfProducts()方法來獲取這個(gè)總數(shù)。我們來創(chuàng)建一個(gè)只讀的屬性,名為TotalRowCount,它返回TotalNumberOfProducts()方法的結(jié)果。
private int TotalRowCount
{
get
{
// Return the value from the TotalNumberOfProducts() method
ProductsBLL productsAPI = new ProductsBLL();
return productsAPI.TotalNumberOfProducts();
}
}
有了這個(gè)屬性后我們現(xiàn)在可以獲取最后一頁的start row index。它可以通過TotalRowCount除以MaximumRows的結(jié)果的整數(shù)部分然后乘以MaximumRows來得到。我們現(xiàn)在可以為4個(gè)分頁界面的button來寫Click event handlers。
最后,在瀏覽第一頁時(shí)需要禁用First 和 Previous buttons,在瀏覽最后一頁時(shí)要禁用Next 和 Last buttons。在ObjectDataSource的Selecting event handler里添加以下代碼:
// Disable the paging interface buttons, if needed
FirstPage.Enabled = StartRowIndex != 0;
PrevPage.Enabled = StartRowIndex != 0;
int LastPageStartRowIndex = ((TotalRowCount - 1) / MaximumRows) * MaximumRows;
NextPage.Enabled = StartRowIndex LastPageStartRowIndex;
LastPage.Enabled = StartRowIndex LastPageStartRowIndex;
完成這些后,瀏覽該頁。見圖15。當(dāng)?shù)谝淮螢g覽該頁時(shí),F(xiàn)irst 和 Previous buttons被禁用。點(diǎn)Next會(huì)顯示第二頁的數(shù)據(jù)。點(diǎn)Last會(huì)顯示最后一頁的數(shù)據(jù)(見圖16和17)。當(dāng)瀏覽最后一頁時(shí),Next 和 Last buttons被禁用。
圖 15: 瀏覽第一頁時(shí) Previous 和 Last Buttons 被禁用
圖 16: 第二頁數(shù)據(jù)
圖 17: 最后一頁
祝編程快樂!
作者簡(jiǎn)介
本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來一直應(yīng)用 微軟Web技術(shù)。大家可以點(diǎn)擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數(shù)據(jù)教程》,希望對(duì)大家的學(xué)習(xí)ASP.NET有所幫助。
您可能感興趣的文章:- ASP.NET2.0數(shù)據(jù)庫入門之SqlDataSource
- SqlDataSource 鏈接Access 數(shù)據(jù)
- aspx中的mysql操作類sqldatasource使用示例分享
- 在ASP.NET 2.0中操作數(shù)據(jù)之三十九:在DataList的編輯界面里添加驗(yàn)證控件
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十:自定義DataList編輯界面
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十一:DataList和Repeater數(shù)據(jù)分頁
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十二:DataList和Repeater數(shù)據(jù)排序(一)
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十四:DataList和Repeater數(shù)據(jù)排序(三)
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十五:DataList和Repeater里的自定義Button
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十六:使用SqlDataSource控件檢索數(shù)據(jù)
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十七:用SqlDataSource控件插入、更新、刪除數(shù)據(jù)