使用兩個 DropDownLis 進行主要/詳細資料篩選 (VB)

作者 :Scott Mitchell

下載 PDF

本教學課程會展開主要/詳細數據關聯性以新增第三層,使用兩個DropDownList控件來選取所需的父和父系記錄。

簡介

上一個教學課程中, 我們已檢查如何使用填入類別的單一DropDownList來顯示簡單的主圖形/詳細數據報表,以及顯示屬於所選類別之產品的 GridView。 此報表模式在顯示具有一對多關聯性的記錄時運作良好,而且可以輕鬆地擴充以用於包含多個一對多關聯性的案例。 例如,訂單項目系統會有對應至客戶、訂單和訂單明細項目的數據表。 指定的客戶可能會有多個訂單,每個訂單都包含多個專案。 這類數據可以向用戶呈現兩個DropDownList和 GridView。 第一個DropDownList會為資料庫中的每一位客戶提供一個清單專案,其中第二個客戶的內容是所選客戶所下訂單。 GridView 會從選取的順序列出明細專案。

雖然 Northwind 資料庫在其 CustomersOrdersOrder Details 數據表中包含標準客戶 / 訂單 / 訂單詳細數據資訊,但這些數據表不會在我們的架構中擷取。 不過,我們仍然可以使用兩個相依的DropDownList來說明。 第一個DropDownList會列出類別,第二個是屬於所選類別的產品。 DetailsView 接著會列出所選產品的詳細數據。

步驟 1:建立和填入類別 DropDownList

我們的第一個目標是新增列出類別的DropDownList。 這些步驟已在上一個教學課程中詳細檢查,但這裡摘要說明是否完整。

MasterDetailsDetails.aspx開啟資料夾中的頁面Filtering、將DropDownList 新增至頁面、將其屬性設定為 Categories,然後按兩下智慧ID標記中的 [設定資料源] 連結。 從 [數據源設定精靈] 選擇新增資料源。

新增DropDownList的新數據源

圖 1:為 DropDownList 新增數據源 (按兩下即可檢視完整大小的影像)

新的數據源自然應該是 ObjectDataSource。 將此新的 ObjectDataSource CategoriesDataSource 命名為 ,並讓它叫 CategoriesBLL 用物件的 GetCategories() 方法。

選擇使用 CategoriesBLL 類別

圖 2:選擇使用 CategoriesBLL 類別 (按鍵即可檢視完整大小的影像)

將 ObjectDataSource 設定為使用 GetCategories () 方法

圖 3:將 ObjectDataSource 設定為使用 GetCategories() 方法 (按兩下即可檢視完整大小的影像)

設定 ObjectDataSource 之後,我們仍然需要指定應該顯示在 DropDownList 中的 Categories 數據源欄位,以及哪一個字段應該設定為清單專案的值。 將 CategoryName 欄位設定為顯示,並 CategoryID 設定為每個清單專案的值。

讓DropDownList顯示CategoryName欄位並使用 CategoryID 作為值

圖 4:讓 DropDownList 顯示 CategoryName 欄位並使用 CategoryID 作為值 (按兩下即可檢視大小完整的影像)

此時,我們有DropDownList控件 (Categories) ,而該控件會填入數據表中的 Categories 記錄。 當使用者從DropDownList選擇新的類別時,我們想要進行回傳,以重新整理我們將在步驟 2 中建立的產品DropDownList。 因此,從 categories DropDownList的智慧標記中檢查 [啟用 AutoPostBack] 選項。

啟用 Category DropDownList 的 AutoPostBack

圖 5:為 DropDownList 啟用 AutoPostBack Categories (按兩下即可檢視完整大小的影像)

步驟 2:在第二個 DropDownList 中顯示選取類別的產品

完成 Categories DropDownList之後,下一個步驟是顯示屬於所選類別的產品DropDownList。 若要完成此作業,請將另一個DropDownList新增至名為 ProductsByCategory的頁面。 Categories如同 DropDownList,為名為 ProductsByCategoryDataSourceProductsByCategory DropDownList 建立新的 ObjectDataSource。

為 ProductsByCategory DropDownList 新增數據源

圖 6:為 DropDownList 新增數據源 ProductsByCategory (按兩下即可檢視大小完整的影像)

建立名為 ProductsByCategoryDataSource 的新 ObjectDataSource

圖 7:建立名為 ProductsByCategoryDataSource 的新 ObjectDataSource (按兩下即可檢視完整大小的影像)

ProductsByCategory由於DropDownList只需要顯示屬於所選類別的這些產品,因此 ObjectDataSource 會從 ProductsBLL 物件叫GetProductsByCategoryID(categoryID)用 方法。

[設定數據源 - productsByCategoryDataSource] 視窗的螢幕快照,其中顯示已選取 ProductsBLL 的商業物件下拉菜單,並醒目提示 [下一步] 按鈕。

圖 8:選擇使用 ProductsBLL 類別 (按鍵即可檢視完整大小的影像)

將 ObjectDataSource 設定為使用 GetProductsByCategoryID (categoryID) 方法

圖 9:將 ObjectDataSource 設定為使用 GetProductsByCategoryID(categoryID) 方法 (按兩下即可檢視全大小影像)

在精靈的最後一個步驟中,我們需要指定 參數的值 categoryID 。 從 Categories DropDownList將此參數指派給選取的專案。

從 Category DropDownList 提取 categoryID 參數值

圖 10:從 Categories DropDownList 提取categoryID參數值 (按兩下即可檢視完整大小的影像)

設定 ObjectDataSource 後,所有保留專案都是指定用於DropDownList項目顯示和值的數據源字段。 ProductName顯示欄位,並使用 ProductID 欄位作為值。

指定 DropDownList 的 ListItems 文字和值屬性所使用的數據源欄位

圖 11:指定 DropDownList 的 ListItemText [數據源欄位] 和 Value [屬性] (按兩下即可檢視完整大小的影像)

設定 ObjectDataSource 和 ProductsByCategory DropDownList 後,我們的頁面會顯示兩個 DropDownList:第一個會列出所有類別,而第二個則會列出屬於所選類別的產品。 當使用者從第一個DropDownList中選取新的類別時,會加入回傳,而第二個DropDownList將會重新系結,顯示屬於新選取類別的產品。 圖 12 和 13 會在透過瀏覽器檢視時顯示 MasterDetailsDetails.aspx 作用中。

第一次瀏覽頁面時,已選取 [篩選類別]

圖 12:第一次瀏覽頁面時,已選取 [篩選類別] (按兩下即可檢視完整大小的影像)

選擇不同的類別會顯示新類別的產品

圖 13:選擇不同的類別顯示新類別的產品, (按兩下即可檢視完整大小的影像)

目前DropDownList在 productsByCategory 變更時 ,不會 造成回傳。 不過,一旦新增 DetailsView 以顯示所選產品的詳細數據, (步驟 3) ,就會想要進行回傳。 因此,從 productsByCategory DropDownList的智慧標記中選取 [啟用 AutoPostBack] 複選框。

啟用產品的 AutoPostBack 功能ByCategory DropDownList

圖 14:啟用DropDownList的 productsByCategory AutoPostBack 功能 (按兩下即可檢視完整大小的影像)

步驟 3:使用 DetailsView 顯示所選產品的詳細數據

最後一個步驟是在 DetailsView 中顯示所選產品的詳細數據。 若要達成此目的,請將DetailsView新增至頁面、將其 ID 屬性設定為 ProductDetails,併為其建立新的 ObjectDataSource。 將這個 ObjectDataSource 設定為使用DropDownList的選取值,從 ProductsBLL 類別的 GetProductByProductID(productID) 方法提取其數據,以取得 參數的值productIDProductsByCategory

[設定數據源 - productsByCategoryDataSource] 視窗的螢幕快照,其中已開啟商務物件下拉功能表。已選取 ProductsBLL,並醒目提示 [下一步] 按鈕。

圖 15:選擇使用 ProductsBLL 類別 (按下即可檢視完整大小的影像)

將 ObjectDataSource 設定為使用 GetProductByProductID (productID) 方法

圖 16:將 ObjectDataSource 設定為使用 GetProductByProductID(productID) 方法 (按兩下即可檢視完整大小的影像)

從 ProductsByCategory DropDownList 提取 productID 參數值

圖 17:從 ProductsByCategory DropDownList 提取productID參數值 (按兩下即可檢視大小完整的影像)

您可以選擇在 DetailsView 中 ProductDetails 顯示任何可用的欄位。 我選擇移除 ProductIDSupplierIDCategoryID 欄位,並重新排序並格式化其餘欄位。 此外,我清除了 DetailsView 的 HeightWidth 屬性,讓 DetailsView 能夠擴充到最佳顯示其數據所需的寬度,而不是使其受限於指定的大小。 完整標記會出現在下方:

<asp:DetailsView ID="ProductDetails" runat="server"
    AutoGenerateRows="False" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="Product" SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName"
          HeaderText="Category" ReadOnly="True"
          SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName"
          HeaderText="Supplier" ReadOnly="True"
          SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit"
           HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice"
           DataFormatString="{0:c}" HeaderText="Price"
            HtmlEncode="False" SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock"
            HeaderText="UnitsInStock"
            SortExpression="Units In Stock" />
        <asp:BoundField DataField="UnitsOnOrder"
            HeaderText="UnitsOnOrder"
            SortExpression="Units On Order" />
        <asp:BoundField DataField="ReorderLevel"
            HeaderText="ReorderLevel" SortExpression="Reorder Level" />
        <asp:CheckBoxField DataField="Discontinued"
            HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

請花點時間在瀏覽器中試用 MasterDetailsDetails.aspx 頁面。 一開始,看起來一切如預期般運作,但有一些細微的問題。 當您選擇新的類別時, ProductsByCategory DropDownList 會更新為包含所選類別的產品,但 ProductDetails DetailsView 會繼續顯示先前的產品資訊。 當為選取的類別選擇不同的產品時,會更新DetailsView。 此外,如果您徹底測試,您會發現,如果您持續選擇新的類別, (例如從 Categories DropDownList 選擇 [篩選]、[Condiments]、[分頁]、[) 所有其他類別選取專案都會重新 ProductDetails 整理 DetailsView。

為了協助串連此問題,讓我們看看特定的範例。 當您第一次瀏覽頁面時,會選取 [篩選] 類別,並將相關產品載入 ProductsByCategory DropDownList 中。 Chai 是選取的產品,其詳細數據會顯示在 DetailsView 中 ProductDetails ,如圖 18 所示。

選取的產品詳細數據會顯示在DetailsView中

圖 18:選取的產品詳細數據會顯示在 DetailsView (Click 以檢視完整大小的影像)

如果您將類別選取範圍從 [訂閱] 變更為 [Condiments],就會發生回傳,並 ProductsByCategory 據以更新 DropDownList,但 DetailsView 仍會顯示 Chai 的詳細數據。

先前選取的產品詳細數據仍會顯示

圖 19:先前選取的產品詳細數據仍會顯示 (按兩下即可檢視大小完整的影像)

從清單中挑選新產品會如預期般重新整理 DetailsView。 如果您在變更產品之後挑選新的類別,則 DetailsView 不會再次重新整理。 不過,如果沒有選擇您選取新類別的新產品,DetailsView 會重新整理。 全球會發生什麼事?

問題是頁面生命週期中的計時問題。 每當要求頁面時,它會在轉譯時繼續進行一些步驟。 在上述其中一個步驟中,ObjectDataSource 控件會檢查其 SelectParameters 值是否已變更。 如果是,系結至 ObjectDataSource 的數據 Web 控件知道它需要重新整理其顯示。 例如,當選取新的類別時, ProductsByCategoryDataSource ObjectDataSource 會偵測其參數值已變更,並 ProductsByCategory 重新系結DropDownList本身,並取得所選類別的產品。

在此情況下發生的問題在於,ObjectDataSources 檢查變更參數的頁面生命週期點是在重新系結相關聯的數據 Web 控件 之前 發生。 因此,選取新的類別時, ProductsByCategoryDataSource ObjectDataSource 會偵測其參數值中的變更。 不過,DetailsView 所使用的 ProductDetails ObjectDataSource 不會注意到任何這類變更,因為 ProductsByCategory DropDownList尚未重新系結。 稍後在生命週期中, ProductsByCategory DropDownList 會將其 ObjectDataSource 重新系結,擷取新選取類別的產品。 ProductsByCategory當DropDownList的值已變更時,ProductDetailsDetailsView 的 ObjectDataSource 已經完成其參數值檢查;因此,DetailsView 會顯示其先前的結果。 此互動描述於圖 20 中。

ProductsByCategory DropDownList 值在 ProductDetails DetailsView 的 ObjectDataSource 檢查變更之後變更

圖 20ProductsByCategory DropDownList 值在 DetailsView 的 ObjectDataSource 檢查變更之後 ProductDetails 變更 (按兩下即可檢視大小完整的影像)

若要解決此問題,我們需要在DropDownList系結之後ProductsByCategory明確重新系結 ProductDetails DetailsView。 當DropDownList DataBound 的事件引發時ProductsByCategory,我們可以藉由呼叫 ProductDetails DetailsView DataBind() 的方法來完成這項作業。 Add the following event handler code to the MasterDetailsDetails.aspx page's code-behind class (refer to the "Programmatically Setting the ObjectDataSource's Parameter Values" for a discussion on how to add an event handler):

Protected Sub ProductsByCategory_DataBound(sender As Object, e As EventArgs) _
    Handles ProductsByCategory.DataBound
        ProductDetails.DataBind()
End Sub

新增對 DetailsView 方法的DataBind()這個明確呼叫ProductDetails之後,本教學課程會如預期般運作。 圖 21 強調此變更如何解決先前的問題。

ProductDetails DetailsView 會在 ProductsByCategory DropDownList 的 DataBound 事件引發時明確重新整理

圖 21ProductDetails當 DropDownList DataBound 的事件引發時ProductsByCategory,詳細數據檢視會明確重新整理 (按兩下即可檢視大小完整的影像)

摘要

DropDownList 可作為主要/詳細數據報表的理想使用者介面元素,其中主要和詳細數據記錄之間有一對多關聯性。 在上述教學課程中,我們已瞭解如何使用單一DropDownList來篩選所選類別所顯示的產品。 在本教學課程中,我們已將產品的 GridView 取代為 DropDownList,並使用 DetailsView 來顯示所選產品的詳細數據。 本教學課程中討論的概念可以輕鬆地延伸至涉及多個一對多關聯性的數據模型,例如客戶、訂單和訂單專案。 一般而言,您一律可以為一對多關聯性中的每個「一」實體新增DropDownList。

快樂的程序設計!

關於作者

Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET

特別感謝

本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的潛在客戶檢閱者是「三元」。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。