由 斯科特·米切爾
在本教學課程中,我們將建置一個使用重複器列出系統中類別的使用者介面,每個類別都會提供按鈕,以使用 BulletedList 控制項顯示其相關聯的產品。
簡介
在過去的十七個 DataList 和 Repeater 教學課程中,我們製作了唯讀範例,以及可進行編輯和刪除操作的範例。 為了在 DataList 中增強編輯和刪除功能,我們在 DataList 的 ItemTemplate 中新增了一些按鈕,這些按鈕在被點擊時會造成回傳,並引發與按鈕的 CommandName 屬性對應的 DataList 事件。 例如,將按鈕新增到 ItemTemplate,其 CommandName 屬性值為 「Edit」 時,會導致在回傳時 DataList 的 EditCommand 引發;而 CommandName 屬性值為 「Delete」 的會引發 DeleteCommand。
除了 [編輯和刪除] 按鈕之外,DataList 和 Repeater 控件也可以包含 Button、LinkButton 或 ImageButton,按一下時會執行一些自定義的伺服器端邏輯。 在這次教學中,我們將建置使用重覆器來列出系統分類的介面。 針對每個類別,重複程式會包含按鈕,以使用 BulletedList 控件來顯示類別的相關聯產品(請參閱圖 1)。
圖 1:點擊 [顯示產品連結] 將類別的產品顯示為項目符號清單(點擊以查看完整大小的影像)
步驟 1:新增自定義按鈕教學網頁
在瞭解如何新增自定義按鈕之前,讓我們先花點時間在網站專案中建立我們在本教學課程所需的 ASP.NET 頁面。 首先,新增名為 CustomButtonsDataListRepeater的新資料夾。 接下來,將下列兩個 ASP.NET 頁面新增至該資料夾,請務必讓每個頁面與 Site.master 主版頁面產生關聯:
Default.aspxCustomButtons.aspx
圖 2:新增自訂 Buttons-Related 教學課程的 ASP.NET 頁面
就像在其他資料夾中一樣, Default.aspx 資料夾中 CustomButtonsDataListRepeater 會列出其區段中的教學課程。 回想一下, SectionLevelTutorialListing.ascx 使用者控件會提供這項功能。 將此使用者控制項從 [方案總管] 拖曳至頁面的設計檢視以新增至 Default.aspx。
圖 3:將使用者控制項新增 SectionLevelTutorialListing.ascx 至 Default.aspx (按兩下以檢視完整大小的影像)
最後,將頁面新增到檔案 Web.sitemap 中。 具體來說,使用 DataList 和 Repeater <siteMapNode>在分頁和排序之後新增下列標記:
<siteMapNode
url="~/CustomButtonsDataListRepeater/Default.aspx"
title="Adding Custom Buttons to the DataList and Repeater"
description="Samples of DataList and Repeater Reports that Include
Buttons for Performing Server-Side Actions">
<siteMapNode
url="~/CustomButtonsDataListRepeater/CustomButtons.aspx"
title="Using Custom Buttons in the DataList and Repeater's Templates"
description="Examines how to add custom Buttons, LinkButtons,
or ImageButtons within templates." />
</siteMapNode>
更新 Web.sitemap之後,請花點時間透過瀏覽器檢視教學課程網站。 左側功能表現在包含編輯、插入和刪除教學的項目。
圖 4:網站地圖現已包含自訂按鈕教學的項目列表
步驟 2:新增類別清單
在本教學課程中,我們需要建立一個重複控制項,其中列出所有類別,並包含一個顯示產品連結按鈕,當點擊時,會在項目符號列表中顯示相關聯的類別產品。 讓我們先建立一個簡單的重複器,用來列出系統中的類別。 首先打開 AdvancedDAL 資料夾中的 EncryptingConfigSections.aspx 頁面。 將 Repeater 從 [工具箱] 拖曳至設計工具,並將其 屬性設定 ID 為 Categories。 接下來,從 Repeater 的智慧標記建立新的數據源控件。 具體而言,請建立名為 CategoriesDataSource 的新 ObjectDataSource 控件,以從 CategoriesBLL 類別 s GetCategories() 方法選取其數據。
圖 5:將 ObjectDataSource 設定為使用 CategoriesBLL 類別 s GetCategories() 方法 (按一下以檢視完整大小的影像)
不同於 DataList 控件,Visual Studio 會根據數據源建立預設值 ItemTemplate ,必須手動定義 Repeater 的範本。 此外,Repeater 的範本必須以宣告方式建立和編輯,也就是說,重複器的智慧標記中並沒有「編輯範本」選項。
點選左下角的 [來源] 索引標籤,新增 ItemTemplate,在 <h3> 元素中顯示類別名稱,並在段落標籤中顯示其描述;包括一個 SeparatorTemplate,在每個類別之間顯示水平線 (<hr />)。 同時新增LinkButton,其 Text 屬性設定為 [顯示產品]。 完成這些步驟之後,您的頁面宣告式標記看起來應該如下所示:
<asp:Repeater ID="Categories" DataSourceID="CategoriesDataSource"
runat="server">
<ItemTemplate>
<h3><%# Eval("CategoryName") %></h3>
<p>
<%# Eval("Description") %>
[<asp:LinkButton runat="server" ID="ShowProducts">
Show Products</asp:LinkButton>]
</p>
</ItemTemplate>
<SeparatorTemplate><hr /></SeparatorTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
圖 6 顯示透過瀏覽器檢視的頁面。 會列出每個類別名稱和描述。 按兩下 [顯示產品] 按鈕會導致回傳,但尚未執行任何動作。
圖 6:顯示每個類別的名稱和描述,以及連結按鈕顯示產品(點擊以查看完整大小的影像)
步驟 3:點擊顯示產品連結按鈕時執行 Server-Side 運算
每當按下 DataList 或 Repeater 範本內的 Button、LinkButton 或 ImageButton 時,就會發生回傳,且 DataList 或 Repeater 的ItemCommand事件被引發。 除了 ItemCommand 事件以外,若按鈕的 CommandName 屬性被設成保留字串(Delete、Edit、Cancel、Update 或 Select)之一,DataList 控件可能會觸發另一個更具體的事件,然而,ItemCommand 事件始終會被觸發。
在 DataList 或 Repeater 控件中點擊按鈕時,我們通常需要傳遞是哪個按鈕被按下(因為控件內可能有多個按鈕,例如 [編輯] 及 [刪除] 按鈕),還可能需要傳遞一些額外資訊(例如按鈕所屬項目的主鍵值)。 Button、LinkButton 和 ImageButton 提供兩個屬性,其值會傳遞至 ItemCommand 事件處理程式:
-
CommandName字串通常用來識別範本中的每個按鈕 -
CommandArgument通常用來保存某些數據欄位的值,例如主鍵值
在此範例中,使用數據系結語法CommandName,將LinkButton s CategoryID 屬性設定為 ShowProducts,並將當前記錄的主鍵值CommandArgument系結至 CategoryArgument='<%# Eval("CategoryID") %>' 屬性。 指定這兩個屬性之後,LinkButton 的宣告式語法看起來應該如下所示:
<asp:LinkButton runat="server" CommandName="ShowProducts"
CommandArgument='<%# Eval("CategoryID") %>' ID="ShowProducts">
Show Products</asp:LinkButton>
按鈕被點擊時,就會發生回傳,並引發 DataList 或 Repeater 的 ItemCommand 事件。 事件處理程式會傳遞按鈕 s CommandName 和 CommandArgument 值。
建立 Repeater s ItemCommand 事件的事件處理程式,並記下傳遞至事件處理程式的第二個參數(名為 e)。 第二個參數的類型 RepeaterCommandEventArgs 如下,具有下列四個屬性:
-
CommandArgument已點選按鈕的屬性值CommandArgument -
CommandName按鈕 sCommandName屬性的值 -
CommandSource指向已點擊的按鈕控制項的參考 -
Item指向RepeaterItem的參考,其中包含所按按鈕;每個綁定到重複器的記錄都呈現為RepeaterItem
由於選取的類別 s CategoryID 是透過 CommandArgument 屬性傳入,因此我們可以取得與事件處理程式中 ItemCommand 所選類別相關聯的產品集合。 然後,這些產品可以系結至尚未新增的 ItemTemplate BulletedList 控件。 接著,剩下的就是新增 BulletedList、在事件處理程式中 ItemCommand 參考它,並將它系結至所選類別的產品集,我們將在步驟 4 中加以處理。
備註
DataList 的 ItemCommand 事件處理程式會接收到一個 DataListCommandEventArgs 類型的物件,該物件提供與 RepeaterCommandEventArgs 類別相同的四個屬性。
步驟 4:在點符清單中顯示選取類別的產品
選取的類別 s 產品可以使用任意數目的控制件顯示在 Repeater s ItemTemplate 內。 我們可以新增另一個巢狀 Repeater、DataList、DropDownList、GridView 等等。 不過,由於我們想要將產品顯示為點符清單,因此我們將使用 BulletedList 控件。 返回 CustomButtons.aspx 頁面的宣告式標記後,在 Show Products LinkButton 的後面新增一個 BulletedList 控制項。 將 BulletedLists 設定 ID 為 ProductsInCategory。 BulletedList 會顯示透過 DataTextField 屬性指定的數據欄位值;由於此控制項將有系結至該欄位的產品資訊,請將 屬性設定 DataTextField 為 ProductName。
<asp:BulletedList ID="ProductsInCategory" DataTextField="ProductName"
runat="server"></asp:BulletedList>
在事件處理程式中 ItemCommand ,使用 e.Item.FindControl("ProductsInCategory") 參考此控件,並將它系結至與所選類別相關聯的產品集合。
protected void Categories_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ShowProducts")
{
// Determine the CategoryID
int categoryID = Convert.ToInt32(e.CommandArgument);
// Get the associated products from the ProudctsBLL and bind
// them to the BulletedList
BulletedList products =
(BulletedList)e.Item.FindControl("ProductsInCategory");
ProductsBLL productsAPI = new ProductsBLL();
products.DataSource =
productsAPI.GetProductsByCategoryID(categoryID);
products.DataBind());
}
}
在事件處理程式中 ItemCommand 執行任何動作之前,請務必先檢查傳入 CommandName的值。 由於ItemCommand事件處理程式會在按一下任何按鈕時引發,因此如果範本中有多個按鈕,請使用CommandName值來辨識要採取的動作。 檢查CommandName 在這裡是多餘的,因為我們只有一個按鈕,但養成這種習慣是個好主意。 接下來,從選取類別的 CategoryID 屬性擷取 CommandArgument 。 然後會參照範本中的 BulletedList 控件,並系結至 ProductsBLL 類別的 GetProductsByCategoryID(categoryID) 方法結果。
在先前使用 DataList 內按鈕的教學課程中,例如 DataList 中編輯和刪除資料的概觀,我們透過 DataKeys 集合判斷指定專案的主鍵值。 雖然此方法適用於 DataList,但 Repeater 沒有 DataKeys 屬性。 相反地,我們必須使用替代方法來提供主鍵值,例如透過按鈕 s CommandArgument 屬性,或將主鍵值指派給範本內的隱藏標籤 Web 控件,並使用 將值讀回 ItemCommand 事件處理程式 e.Item.FindControl("LabelID")。
完成 ItemCommand 事件處理程序之後,請花點時間在瀏覽器中測試此頁面。 如圖 7 所示,點選 [顯示產品] 連結會造成回傳,並在 BulletedList 中顯示所選類別的產品。 此外,請注意,即使按兩下其他類別顯示產品連結,此產品資訊仍會維持不變。
備註
如果您要修改此報表的行為,因此一次只列出一個類別的產品,只要將 BulletedList 控制件的 EnableViewState 屬性設定為 False。
圖 7:項目符號清單用來顯示所選類別的產品(按兩下即可檢視完整大小的影像)
總結
DataList 和 Repeater 控制項可以在其範本中包含任意數目的 Button、LinkButtons 或 ImageButton。 按一下這些按鈕時,會導致回傳並引發 ItemCommand 事件。 若要將自定義伺服器端動作與按下的按鈕產生關聯,請建立 ItemCommand 事件的事件處理程式。 在此事件處理程式中,請先檢查傳入 CommandName 值,以判斷已按下哪個按鈕。 您可以選擇性地透過按鈕 s CommandArgument 屬性提供其他資訊。
快樂的程序設計!
關於作者
斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是《Sams 24小時自學ASP.NET 2.0》。 可以聯絡他 mitchell@4GuysFromRolla.com。
特別感謝
本教學系列已由許多熱心的評論者審閱。 本教學課程的主要檢閱者是 Dennis Patterson。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請在 mitchell@4GuysFromRolla.com給我留言。