共用方式為


使用重複項控制項與資料清單跨兩個頁面的主要 /詳細資料篩選 (VB)

由斯科特· 米切爾

下載 PDF

在本教學課程中,我們將探討如何跨兩頁分隔主要/詳細數據報表。 在 [主版] 頁面中,我們使用 Repeater 控件來轉譯類別清單,當按兩下時,會將使用者帶到 [詳細數據] 頁面,其中兩欄 DataList 會顯示屬於所選類別的產品。

簡介

在主要 /詳細數據跨兩頁 篩選教學課程中,我們已使用 GridView 檢查此模式,以顯示系統中的所有供應商。 此 GridView 包含 HyperLinkField,該欄位會轉譯為第二頁的連結,並在 SupplierID querystring 中傳遞 。 第二頁使用 GridView 列出所選供應商所提供的產品。

這類雙頁主版/詳細數據報表也可以使用DataList和Repeater控件來完成。 唯一的差別在於 DataList 和 Repeater 都不支援 HyperLinkField 控件。 相反地,我們必須在控件 的 ItemTemplate內新增 HyperLink Web 控件或錨點 HTML 元素 (<a>)。 接著,您可以使用宣告式或程序設計方法來自定義 HyperLink NavigateUrl 的屬性或錨點 href 的屬性。

在本教學課程中,我們將探索使用 Repeater 控件,在單一頁面上列出點符清單中的類別範例。 每個清單專案都會包含類別的名稱和描述,類別名稱會顯示為第二頁的連結。 按兩下此連結會將使用者移至第二個頁面,其中 DataList 會顯示屬於所選類別的產品。

步驟 1:在點符清單中顯示類別

建立任何主要/詳細數據報表的第一個步驟是從顯示「主要」記錄開始。 因此,我們的第一個工作是在「主版」頁面中顯示類別。 CategoryListMaster.aspx開啟資料夾中的頁面DataListRepeaterFiltering、新增 Repeater 控制件,然後從智慧標記選擇新增 ObjectDataSource。 設定新的 ObjectDataSource,使其從 CategoriesBLL 類別的 GetCategories 方法存取其數據(請參閱圖 1)。

將 ObjectDataSource 設定為使用 CategoriesBLL 類別的 GetCategories 方法

圖 1:將 ObjectDataSource 設定為使用 CategoriesBLL 類別的 GetCategories 方法 (按一下以檢視完整大小的影像

接下來,定義 Repeater 的範本,使其將每個類別名稱和描述顯示為專案符號清單中的專案。 現在,我們不必擔心每個類別連結至詳細數據頁面。 下列顯示 Repeater 和 ObjectDataSource 的宣告式標記:

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"
    EnableViewState="False">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
 
    <ItemTemplate>
        <li><%# Eval("CategoryName") %> - <%# Eval("Description") %></li>
    </ItemTemplate>
 
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
 
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

完成此標記之後,請花點時間透過瀏覽器檢視我們的進度。 如圖 2 所示,重複項會轉譯為點符清單,其中顯示每個類別的名稱和描述。

每個類別都會顯示為點符清單專案

圖 2:每個類別都會顯示為點符清單專案(按兩下以檢視完整大小的影像

若要允許使用者顯示指定類別的「詳細數據」信息,我們需要新增每個點符清單專案的連結,按兩下時,使用者將會前往第二頁(ProductsForCategoryDetails.aspx)。 第二頁接著會使用 DataList 顯示所選類別的產品。 若要判斷已按下其鏈接的類別,我們需要透過某些機制將點擊類別的 CategoryID 傳遞至第二頁。 將純量數據從某個頁面傳送到另一個頁面最簡單的最簡單方式是透過 querystring,這是我們將在本教學課程中使用的選項。 特別是, ProductsForCategoryDetails.aspx 頁面會預期選取 categoryID 的值會透過名為 CategoryID的querystring字段傳遞。 例如,若要檢視 [飲料] 類別的產品,其值為 CategoryID 1,使用者將會造訪 ProductsForCategoryDetails.aspx?CategoryID=1

若要在 Repeater 中為每個點符清單專案建立超連結,我們需要將 HyperLink Web 控制件或 HTML 錨點專案 (<a>) 新增至 ItemTemplate。 在針對每個數據列顯示超連結相同的案例中,任一種方法都已足夠。 對於 Repeaters,我偏好使用錨點元素。 若要使用錨點元素,請將 Repeater 的 ItemTemplate 更新為:

<li>
    <a href='ProductsForCategoryDetails.aspx?CategoryID=<%# Eval("CategoryID") %>'>
        <%# Eval("CategoryName") %>
    </a> - <%# Eval("Description") %>
</li>

請注意, CategoryID 可以直接插入錨點元素的 href 屬性;不過,若要這樣做,請務必使用 href 單引號分隔屬性的值,因為 Eval 屬性內的 href 方法會以引號分隔其字串 ("CategoryID") 。 或者,可以改用 HyperLink Web 控制項:

<li>
    <asp:HyperLink runat="server" Text='<%# Eval("CategoryName") %>'
        NavigateUrl='<%# "ProductsForCategoryDetails.aspx?CategoryID=" &
            Eval("CategoryID") %>'>
    </asp:HyperLink>
    - <%# Eval("Description") %>
</li>

請注意 URL 的靜態部分 — ProductsForCategoryDetails.aspx?CategoryID — 會使用字串串連直接附加至數據系結語法內的結果 Eval("CategoryID")

使用 HyperLink 控制件的其中一個優點是,如有需要,可以從 Repeater 的 ItemDataBound 事件處理程式以程式設計方式存取它。 例如,您可能想要將類別名稱顯示為文字,而不是作為沒有相關聯產品之類別的連結。 這類檢查可以在事件處理程式中 ItemDataBound 以程序設計方式執行;對於沒有相關聯產品的類別,HyperLink 的 NavigateUrl 屬性可以設定為空白字串,因而導致該特定類別名稱轉譯為純文本(而非連結)。 如需根據事件處理程式以程式設計邏輯ItemDataBound格式化 DataList 和 Repeater 內容的詳細資訊,請參閱根據 DataList 和 Repeater 的格式化 DataList 和 Repeater 數據教學課程。

如果您跟著做,請隨意在頁面中使用錨點元素或 HyperLink 控件方法。 無論使用何種方法,透過瀏覽器檢視頁面時,每個類別名稱都應該轉譯為的連結 ProductsForCategoryDetails.aspx,並傳入適用的 CategoryID 值(請參閱圖 3)。

類別名稱現在連結至ProductsForCategoryDetails.aspx

圖 3:類別名稱現在連結至 ProductsForCategoryDetails.aspx按兩下以檢視完整大小的影像

步驟 3:列出屬於所選類別的產品

完成頁面之後 CategoryListMaster.aspx ,我們已準備好將注意力轉向實作「詳細數據」頁面 ProductsForCategoryDetails.aspx。 開啟此頁面,將 DataList 從工具箱拖曳至設計工具,並將其屬性設定 IDProductsInCategory。 接下來,從 DataList 的智慧標記選擇將新的 ObjectDataSource 新增至頁面,將它命名為 ProductsInCategoryDataSource。 設定它,使其呼叫 ProductsBLL 類別的 GetProductsByCategoryID(categoryID) 方法;將 INSERT、UPDATE 和 DELETE 索引標籤中的下拉式清單設定為 [無]。

將 ObjectDataSource 設定為使用 ProductsBLL 類別的 GetProductsByCategoryID(categoryID) 方法

圖 4:將 ObjectDataSource 設定為使用 ProductsBLL 類別的方法 GetProductsByCategoryID(categoryID)按兩下以檢視完整大小的影像

GetProductsByCategoryID(categoryID)由於 方法接受輸入參數 (categoryID), [選擇數據源精靈] 提供我們指定參數來源的機會。 使用 QueryStringField CategoryID將參數來源設定為 QueryString 。

使用 Querystring 字段類別識別碼作為參數的來源

圖 5:使用 Querystring 欄位 CategoryID 作為參數的來源 (按兩下以檢視完整大小的影像

如先前教學課程中所見,完成 [選擇數據源精靈] 之後,Visual Studio 會自動為 DataList 建立 , ItemTemplate 其中列出每個數據功能變數名稱和值。 將此範本取代為只列出產品名稱、供應商和價格的範本。 此外,將 DataList 的 RepeatColumns 屬性設定為 2。 這些變更之後,DataList 和 ObjectDataSource 的宣告式標記看起來應該如下所示:

<asp:DataList ID="ProductsInCategory" DataKeyField="ProductID" RepeatColumns="2"
    DataSourceID="ProductsInCategoryDataSource" EnableViewState="False"
    runat="server">
    <ItemTemplate>
        <h5><%# Eval("ProductName") %></h5>
        <p>
            Supplied by <%# Eval("SupplierName") %><br />
            <%# Eval("UnitPrice", "{0:C}") %>
        </p>
    </ItemTemplate>
</asp:DataList>
 
<asp:ObjectDataSource ID="ProductsInCategoryDataSource"
    OldValuesParameterFormatString="original_{0}" runat="server"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" QueryStringField="CategoryID"
            Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

若要檢視此頁面的運作情形,請從 CategoryListMaster.aspx 頁面開始;接下來,按兩下類別項目符號清單中的連結。 這麼做會帶您前往 ProductsForCategoryDetails.aspx,並 CategoryID 透過querystring 傳遞 。 中的 ProductsInCategoryDataSource ObjectDataSource ProductsForCategoryDetails.aspx 將只取得指定類別的這些產品,並在 DataList 中顯示它們,這會針對每個數據列轉譯兩個產品。 圖 6 顯示檢視飲料時的螢幕快照 ProductsForCategoryDetails.aspx

飲料會顯示,每列兩個

圖 6:顯示飲料,每列兩個 (按兩下以檢視全尺寸影像

步驟 4:顯示ProductsForCategoryDetails.aspx的類別資訊

當使用者按兩下中的 CategoryListMaster.aspx類別時,系統會將他們帶到 ProductsForCategoryDetails.aspx 並顯示屬於所選類別的產品。 不過,在 中 ProductsForCategoryDetails.aspx ,沒有選取類別的視覺提示。 一個使用者,意在按兩下飲料,但意外點擊調味品,沒有辦法意識到他們的錯誤,一旦他們到達 ProductsForCategoryDetails.aspx。 為了減輕此潛在問題,我們可以在頁面頂端 ProductsForCategoryDetails.aspx 顯示所選類別的相關信息,也就是其名稱和描述。

若要達成此目的,請在 中的 ProductsForCategoryDetails.aspxRepeater 控件上方新增 FormView。 接下來,將新的 ObjectDataSource 新增至 FormView 智慧標記的頁面, CategoryDataSource 並將其設定為使用 CategoriesBLL 類別的 GetCategoryByCategoryID(categoryID) 方法。

透過 CategoriesBLL 類別的 GetCategoryByCategoryID(categoryID) 方法存取類別的相關信息

圖 7:透過 CategoriesBLL 類別的 GetCategoryByCategoryID(categoryID) 方法存取類別的相關信息(按兩下以檢視完整大小的影像

ProductsInCategoryDataSource如同在步驟 3 中新增的 ObjectDataSource,CategoryDataSource「設定數據源精靈」會提示我們輸入方法輸入參數的來源GetCategoryByCategoryID(categoryID)。 使用與之前完全相同的設定,將參數來源設定為 QueryString,並將 QueryStringField 值 CategoryID 設定為 (請參閱圖 5)。

完成精靈之後,Visual Studio 會自動為 FormView 建立 ItemTemplateEditItemTemplateInsertItemTemplate 。 因為我們提供唯讀介面,因此您可以隨意移除 EditItemTemplateInsertItemTemplate。 此外,您也可以隨意自定義 FormView 的 ItemTemplate。 拿掉多餘的範本並自定義 ItemTemplate 之後,FormView 和 ObjectDataSource 的宣告式標記看起來應該如下所示:

<asp:FormView ID="FormView1" runat="server" DataKeyNames="CategoryID"
    DataSourceID="CategoryDataSource" EnableViewState="False" Width="100%">
    <ItemTemplate>
        <h3>
            <asp:Label ID="CategoryNameLabel" runat="server"
                Text='<%# Bind("CategoryName") %>' />
        </h3>
        <p>
            <asp:Label ID="DescriptionLabel" runat="server"
                Text='<%# Bind("Description") %>' />
        </p>
    </ItemTemplate>
</asp:FormView>
 
<asp:ObjectDataSource ID="CategoryDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategoryByCategoryID" TypeName="CategoriesBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" Type="Int32"
            QueryStringField="CategoryID" />
    </SelectParameters>
</asp:ObjectDataSource>

圖 8 顯示透過瀏覽器檢視此頁面時的螢幕快照。

注意

除了 FormView 之外,我還在 FormView 上方新增了 HyperLink 控件,將使用者帶回類別清單(CategoryListMaster.aspx)。 請隨意將這個連結放在別處或完全省略。

類別信息現在會顯示在頁面頂端

圖 8:類別資訊現在會顯示在頁面頂端(按兩下以檢視完整大小的影像

步驟 5:如果沒有任何產品屬於選取的類別,則顯示訊息

不論是否有任何相關聯的產品,頁面 CategoryListMaster.aspx 都會列出系統中的所有類別。 如果使用者按兩下沒有相關聯產品的類別,將不會轉譯 中的 ProductsForCategoryDetails.aspx DataList,因為其數據源不會有任何專案。 如我們過去教學課程中所見,GridView 提供屬性 EmptyDataText ,可用來指定文字訊息,以在其數據源中沒有記錄時顯示。 不幸的是,DataList 和 Repeater 都沒有這類屬性。

若要顯示訊息,告知用戶選取的類別沒有相符的產品,我們需要將標籤件新增至已指派屬性的頁面 Text ,以便在沒有相符產品的情況下顯示訊息。 然後,我們需要根據 DataList 是否包含任何專案,以程式設計方式設定其 Visible 屬性。

若要達成此目的,請從在 DataList 底下新增標籤開始。 將其 ID 屬性設定為 NoProductsMessage ,並將其 Text 屬性設定為 「沒有所選類別的產品」。。接下來,我們需要根據是否有任何數據系結至 ProductsInCategory DataList,以程式設計方式設定此標籤Visible的屬性。 此指派必須在數據系結至 DataList 之後進行。 針對 GridView、DetailsView 和 FormView,我們可以為控件的事件 DataBound 建立事件處理程式,該事件處理程式會在數據系結完成之後引發。 不過,DataList 和 Repeater DataBound 都沒有可用的事件。

在此特定範例中,我們可以在事件處理程式中Page_Load指派 Label 的 Visible 屬性,因為數據會在頁面Load的事件之前指派給 DataList。 不過,此方法在一般情況下無法運作,因為 ObjectDataSource 中的數據可能會在頁面生命週期稍後系結至 DataList。 例如,如果顯示的數據是以另一個控件中的值為基礎,例如,當使用DropDownList顯示主數據/詳細數據報表來保存“master” 記錄時,數據在頁面生命週期中的階段之前 PreRender ,可能不會反彈至數據 Web 控件。

系結 或 的項目類型ItemAlternatingItem時,所有案例都能運作的其中一個解決方案,就是在 DataList 的 ItemDataBound (或ItemCreated) 事件處理程式中將 屬性指派VisibleFalse 。 在這種情況下,我們知道數據源中至少有一個數據項,因此可以隱藏標籤 NoProductsMessage 。 除了這個事件處理程式之外,我們也需要 DataList DataBinding 事件的事件處理程式,其中我們會將 Label 的 Visible 屬性初始化為 TrueDataBinding由於事件會在事件之前ItemDataBound引發,所以 Label 的 Visible 屬性一開始會設定為 True;不過,如果有任何數據項,則會設定為 False。 下列程式代碼會實作此邏輯:

Protected Sub ProductsInCategory_DataBinding(sender As Object, e As EventArgs) _
    Handles ProductsInCategory.DataBinding
    'Show the Label
    NoProductsMessage.Visible = True
End Sub
 
Protected Sub ProductsInCategory_ItemDataBound(s As Object, e As DataListItemEventArgs) _
    Handles ProductsInCategory.ItemDataBound
    'If we have a data item, hide the Label
    If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = _
        ListItemType.AlternatingItem Then
 
        NoProductsMessage.Visible = False
    End If
End Sub

Northwind 資料庫中的所有類別都與一或多個產品相關聯。 為了測試這項功能,我已手動調整本教學課程的 Northwind 資料庫,並將與產生類別 (CategoryID = 7) 相關聯的所有產品重新指派給海鮮類別 (CategoryID = 8)。 這可以從 [伺服器總管] 中選擇 [新增查詢] 並使用下列 UPDATE 語句來完成:

UPDATE Products SET
    CategoryID = 8
WHERE CategoryID = 7

據此更新資料庫之後,返回 CategoryListMaster.aspx 頁面,然後按兩下 [產生] 連結。 由於不再有任何屬於 [產生] 類別的產品,您應該會看到「選取的類別沒有產品...」。訊息,如圖 9 所示。

如果沒有屬於選取類別的產品,則會顯示訊息

圖 9:如果沒有屬於所選類別的產品,則會顯示訊息(按兩下即可檢視完整大小的影像

摘要

雖然主報表/詳細數據報表可以在單一頁面上同時顯示主圖形和詳細數據記錄,但在許多網站中,它們會跨兩個網頁分開。 在本教學課程中,我們探討如何使用「主要」網頁中的重複項清單,以及列在「詳細數據」頁面中的相關聯產品,來實作這類主要/詳細數據報表。 主版網頁中的每個清單專案都包含沿著數據列 CategoryID 值傳遞的詳細數據頁面連結。

在擷取指定供應商產品的詳細數據頁面中,是透過 ProductsBLL 類別的方法完成的 GetProductsByCategoryID(categoryID) 。 參數 categoryID 值是以宣告方式使用 CategoryID querystring 值做為參數來源來指定。 我們也查看了如何使用 FormView 在詳細數據頁面中顯示類別詳細數據,以及如何在沒有任何屬於所選類別的產品時顯示訊息。

快樂的程序設計!

關於作者

斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 2.0。 他可以到達 mitchell@4GuysFromRolla.com, 或通過他的博客,可以在 找到 http://ScottOnWriting.NET

特別感謝...

本教學課程系列已由許多實用的檢閱者檢閱。 本教學課程的主要檢閱者是 Zack Jones 和 Liz Shulok。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。