在ASP.NET 2.0中操作數(shù)據(jù)之四十三:DataList和Repeater數(shù)據(jù)排序(二)
接著上篇介紹,上篇已經(jīng)通過DropDownList簡單實現(xiàn)了排序的功能,下面讓我們看看帶有分頁的排序該怎么做。
第五步: 為使用默認分頁的DataList添加排序的支持
打開PagingSortingDataListRepeater文件夾里的SortingWithDefaultPaging.aspx和Paging.aspx 頁。在Paging.aspx 頁里查看源文件。將圖8里選擇的文本復(fù)制下來,然后粘貼到SortingWithDefaultPaging.aspx 頁里的<asp:Content> 標簽內(nèi)。
圖 8: 復(fù)制粘貼代碼
然后將Paging.aspx頁后臺代碼里的屬性和方法也粘貼到SortingWithDefaultPaging.aspx頁后臺代碼里?,F(xiàn)在瀏覽SortingWithDefaultPaging.aspx頁,它現(xiàn)在應(yīng)該有和Paging.aspx頁一樣的外觀和功能。
在ProductsBLL 里添加默認的分頁和排序方法
前面一章里我們在ProductsBLL類里創(chuàng)建了一個GetProductsAsPagedDataSource(pageIndex, pageSize)方法,它返回一個PagedDataSource對象。這個對象通過BLL的GetProducts()方法獲取所有的product,然而綁定到DataList的只是那些和輸入?yún)?shù)pageIndex 和 pageSize 相關(guān)的記錄。
本章前面我們已經(jīng)通過在ObjectDataSource的 Selecting event handler里指定sort expression來添加了排序功能。當ObjectDataSource返回可排序?qū)ο髸r這個方法運轉(zhuǎn)的很好,比如GetProducts()方法返回的ProductsDataTable。然而GetProductsAsPagedDataSource方法返回的PagedDataSource對象并不支持對它內(nèi)部數(shù)據(jù)的排序,因此我們需要在將數(shù)據(jù)放入PagedDataSource前對GetProducts()方法返回的記錄進行排序。
在ProductsBLL類里建一個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方法有一點不一樣。GetProductsSortedAsPagedDataSource多了一個sortExpression參數(shù),將它的值賦給ProductDataTable的 DefaultView的Sort屬性。并將ProductDataTable的DefaultView賦給PagedDataSource對象的DataSource。
調(diào)用 GetProductsSortedAsPagedDataSource 方法并指定輸入?yún)?shù)SortExpression的值
完成這些后,下一步需要提供參數(shù)值。SortingWithDefaultPaging.aspx頁的ObjectDataSource現(xiàn)在被配置用來調(diào)用GetProductsAsPagedDataSource方法并通過兩個QueryStringParameters來傳遞參數(shù),這些參數(shù)在SelectParameters集合里已經(jīng)指定了。這兩個QueryStringParameters參數(shù)表示GetProductsAsPagedDataSource方法的pageIndex 和 pageSize 參數(shù)從querystring里獲取。
修改ObjectDataSource的SelectMethod屬性,讓它調(diào)用GetProductsSortedAsPagedDataSource方法。然后添加一個新的QueryStringParameter來讓sortExpression 參數(shù)通過querystring的sortExpression字段獲取。將QueryStringParameter的默認值設(shè)為“ProductName”。
現(xiàn)在ObjectDataSource的聲明標記語言看起來應(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頁會按照product name的字母順序排序。見圖9。這是因為GetProductsSortedAsPagedDataSource方法的sortExpression 參數(shù)的默認值為“ProductName”。
圖 9: 默認的按照 ProductName 排序
如果你手動添加一個sortExpression querystring字段–比如SortingWithDefaultPaging.aspx?sortExpression=CategoryName –那么結(jié)果會以指定的sortExpression來排序。然而在轉(zhuǎn)到另外一個頁時這個sortExpression參數(shù)并沒有包含在querystring里。實際上當點上或者下一頁時我們會返回Paging.aspx。而且當前并沒有排序界面。用戶可以改變數(shù)據(jù)排序的唯一方法是直接操作querystring。
創(chuàng)建排序界面
我們首先要修改RedirectUser方法來將用戶重定向到SortingWithDefaultPaging.aspx頁(而不是Paging.aspx),并將sortExpression的值包含到querystring里。我們還應(yīng)該添加一個只讀的SortExpression屬性。這個屬性和前面一章里創(chuàng)建的PageIndex 和 PageSize屬性相似,在sortExpression querystring字段存在時返回它的值,否則的話使用默認值“ProductName”。
現(xiàn)在的RedirectUser方法只接收一個參數(shù)–顯示的頁的index。然而可能有些時候我們需要使用排序表達式將用戶重定向到特定數(shù)據(jù)的頁。我們將馬上來為這個頁創(chuàng)建排序界面,它將包含一些button來為指定的列排序。當其中一個button被點擊時,我們需要傳入合適的排序表達式的值來重定向用戶。為了提供這個功能,創(chuàng)建兩個RedirectUser方法。第一個接收page的index,第二個接收page index和sort expression(排序表達式)。
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)); }
本章的第一個例子里,我們使用DropDownList來創(chuàng)建了一個排序界面。我們將在這個例子里使用3個button(它們位于DataList上方)–一個表示為ProductName排序,一個為CategoryName,一個為SupplierName。添加三個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>
然后為每個button創(chuàng)建一個Click event handler。這個事件處理將調(diào)用RedirectUser方法,并使用合適的排序表達式將用戶返回到第一頁。
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ù)據(jù)將按照product name的字母順序排序(見圖9)。點Next button來瀏覽第二頁,然后點“Sort by Category” button。這樣將讓頁返回到第一頁,并按照category name來排序,見圖10。同樣的,點“Sort by Supplier” button會將數(shù)據(jù)按照supplier排序,并返回到第一頁。當數(shù)據(jù)分頁時排序的選擇會被記下來。圖11是按照category排序并瀏覽第十三頁的樣子。
圖 10: Products 按照Category排序
圖 11: 分頁時會記下Sort Expression
第六步: Repeater的自定義分頁
第五步里的DataList示例使用默認的分頁技術(shù)。當大數(shù)據(jù)量時,我們需要使用自定義分頁?;氐紼fficiently Paging Through Large Amounts of Data 和 Sorting Custom Paged Data 里,我們學習了默認和自定義這兩種分頁方式的不同,并在BLL里為自定義分頁和對自定義分頁數(shù)據(jù)的排序創(chuàng)建了方法。在這兩章里我們在ProductsBLL里添加了下面三個方法:
GetProductsPaged(startRowIndex, maximumRows) – 返回從startRowIndex開始并不超過maximumRows 的特定記錄集。
GetProductsPagedAndSorted(sortExpression, startRowIndex, maximumRows) – 根據(jù)指定的sortExpression 返回特定記錄集。
TotalNumberOfProducts() – 提供Products 表的總記錄數(shù)。
這些方法可以用來在DataList或Repeater進行高效的分頁并排序。我們首先創(chuàng)建一個支持自定義分頁的Repeater。然后再添加排序支持。打開PagingSortingDataListRepeater文件夾下的SortingWithCustomPaging.aspx頁,添加一個Repeater,將ID設(shè)為Products。從智能標簽里創(chuàng)建一個名為ProductsDataSource的ObjectDataSource。使用ProductsBLL類的GetProductsPaged方法來配置它的select標簽。
圖 12: 配置 ObjectDataSource
在UPDATE, INSERT, DELETE標簽里選擇“(None)”,點下一步。現(xiàn)在我們需要為GetProductsPaged方法的startRowIndex 和 maximumRows 參數(shù)選擇源。實際上這里不需要配置。這兩個參數(shù)的值會在ObjectDataSource的Selecting event handler里通過Arguments屬性來指定,就好象我們在本章的第一個例子里指定sortExpression 一樣。因此,在參數(shù)源的下拉列表里選擇“None”。
圖 13:將參數(shù)源設(shè)為 “None”
注意:不要將ObjectDataSource的EnablePaging屬性設(shè)為true。這樣會讓ObjectDataSource自動的將它的startRowIndex 和 maximumRows 參數(shù)包含在SelectMethod的已經(jīng)存在的參數(shù)列表里。EnablePaging屬性在將自定義分頁數(shù)據(jù)綁定到GridView, DetailsView, FormView時才有用。由于我們是為DataList 和Repeater手動添加分頁支持,因此將它們設(shè)為false(默認的),我們將在ASP.NET頁里直接實現(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)在瀏覽該頁,注意沒有返回任何記錄。這是因為我們還沒有指定startRowIndex 和 maximumRows 參數(shù)的值。為了指定這些值,為ObjectDataSource的Selecting event創(chuàng)建一個event handler,并將參數(shù)值硬編碼的設(shè)置為0和5。
protected void ProductsDataSource_Selecting (object sender, ObjectDataSourceSelectingEventArgs e) { e.InputParameters["startRowIndex"] = 0; e.InputParameters["maximumRows"] = 5; }
現(xiàn)在瀏覽頁面時會顯示前5條product記錄。
圖 14: 顯示前5條product
注意:圖14列出的products以product name排序是因為自定義分頁使用的GetProductsPaged存儲過程返回的結(jié)果是以ProductName排序。
為了讓用戶可以翻頁,我們需要在postback過程中記下start row index 和 maximum rows。在默認分頁的例子里我們用querystring來保存這些值。這個例子里我們將使用view state。創(chuàng)建下面兩個屬性:
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)建分頁界面了。
添加分頁界面
我們還是使用和默認分頁例子里一樣的First, Previous, Next, Last分頁界面,并包含顯示當前是哪頁和總頁數(shù)的label。在Repeater下面添加4個button和1一個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個button創(chuàng)建Click event handlers。當其中一個button被點時,我們需要修改StartRowIndex并將數(shù)據(jù)重新綁定到Repeater。First, Previous, 和 Next button的代碼都非常簡單,但是對Last button來說,我們?nèi)绾闻袛嘧詈笠豁摂?shù)據(jù)的start row index?為了計算出這個index–和判斷Next 和 Last button是否應(yīng)該enabled一樣–我們需要知道分頁數(shù)據(jù)的總數(shù)。我們可以調(diào)用ProductsBLL類的TotalNumberOfProducts()方法來獲取這個總數(shù)。我們來創(chuàng)建一個只讀的屬性,名為TotalRowCount,它返回TotalNumberOfProducts()方法的結(jié)果。
private int TotalRowCount { get { // Return the value from the TotalNumberOfProducts() method ProductsBLL productsAPI = new ProductsBLL(); return productsAPI.TotalNumberOfProducts(); } }
有了這個屬性后我們現(xiàn)在可以獲取最后一頁的start row index。它可以通過TotalRowCount除以MaximumRows的結(jié)果的整數(shù)部分然后乘以MaximumRows來得到。我們現(xiàn)在可以為4個分頁界面的button來寫Click event handlers。
最后,在瀏覽第一頁時需要禁用First 和 Previous buttons,在瀏覽最后一頁時要禁用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。當?shù)谝淮螢g覽該頁時,F(xiàn)irst 和 Previous buttons被禁用。點Next會顯示第二頁的數(shù)據(jù)。點Last會顯示最后一頁的數(shù)據(jù)(見圖16和17)。當瀏覽最后一頁時,Next 和 Last buttons被禁用。
圖 15: 瀏覽第一頁時 Previous 和 Last Buttons 被禁用
圖 16: 第二頁數(shù)據(jù)
圖 17: 最后一頁
祝編程快樂!
作者簡介
本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來一直應(yīng)用 微軟Web技術(shù)。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數(shù)據(jù)教程》,希望對大家的學習ASP.NET有所幫助。
- ASP.NET2.0數(shù)據(jù)庫入門之SqlDataSource
- SqlDataSource 鏈接Access 數(shù)據(jù)
- aspx中的mysql操作類sqldatasource使用示例分享
- 在ASP.NET 2.0中操作數(shù)據(jù)之三十九:在DataList的編輯界面里添加驗證控件
- 在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ù)
相關(guān)文章
NopCommerce架構(gòu)分析之(三)EntityFramework數(shù)據(jù)庫初試化及數(shù)據(jù)操作
本文介紹IStartupTask,該類會在系統(tǒng)啟動時執(zhí)行,IStartupTask調(diào)用IEfDataProvider進行數(shù)據(jù)庫的初始化。2016-04-04在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
前面幾節(jié)我們講解了ASP.NET中如何上傳顯示二進制圖片數(shù)據(jù),這一節(jié)我們來介紹一下如何在GridView編輯和刪除已經(jīng)存在的二進制數(shù)據(jù)。2016-05-05在ASP.NET 2.0中操作數(shù)據(jù)之四十一:DataList和Repeater數(shù)據(jù)分頁
DataList 和Repeater 都沒有提供內(nèi)置的分頁和排序功能,本文主要介紹利用PagedDataSource實現(xiàn)DataList和Repeater數(shù)據(jù)分頁。2016-05-05在ASP.NET 2.0中操作數(shù)據(jù)之六十八:為DataTable添加額外的列
本文介紹并使用TableAdapter向DataTable添加新的一列的方法和步驟,任何時候只要重新運行TableAdapter設(shè)置向?qū)?,用戶所做的所有定制都要被覆蓋,為避免出現(xiàn)這種情況,我們建議直接修改存儲過程。2016-05-05AlternatingItemTemplate類似于 ItemTemplate 元素
AlternatingItemTemplate類似于 ItemTemplate 元素...2006-10-10.NET多種數(shù)據(jù)庫大數(shù)據(jù)批量插入、更新(支持SqlServer、MySql、PgSql和Oracle)
這篇文章介紹了.NET多種數(shù)據(jù)庫大數(shù)據(jù)批量插入、更新。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-11-11