使用兩個 DropDownLis 進行主要/詳細資料篩選 (VB)
本教學課程會展開主要/詳細數據關聯性以新增第三層,使用兩個DropDownList控件來選取所需的父和父系記錄。
簡介
在 上一個教學課程中, 我們已檢查如何使用填入類別的單一DropDownList來顯示簡單的主圖形/詳細數據報表,以及顯示屬於所選類別之產品的 GridView。 此報表模式在顯示具有一對多關聯性的記錄時運作良好,而且可以輕鬆地擴充以用於包含多個一對多關聯性的案例。 例如,訂單項目系統會有對應至客戶、訂單和訂單明細項目的數據表。 指定的客戶可能會有多個訂單,每個訂單都包含多個專案。 這類數據可以向用戶呈現兩個DropDownList和 GridView。 第一個DropDownList會為資料庫中的每一位客戶提供一個清單專案,其中第二個客戶的內容是所選客戶所下訂單。 GridView 會從選取的順序列出明細專案。
雖然 Northwind 資料庫在其 Customers
、 Orders
和 Order Details
數據表中包含標準客戶 / 訂單 / 訂單詳細數據資訊,但這些數據表不會在我們的架構中擷取。 不過,我們仍然可以使用兩個相依的DropDownList來說明。 第一個DropDownList會列出類別,第二個是屬於所選類別的產品。 DetailsView 接著會列出所選產品的詳細數據。
步驟 1:建立和填入類別 DropDownList
我們的第一個目標是新增列出類別的DropDownList。 這些步驟已在上一個教學課程中詳細檢查,但這裡摘要說明是否完整。
MasterDetailsDetails.aspx
開啟資料夾中的頁面Filtering
、將DropDownList 新增至頁面、將其屬性設定為 Categories
,然後按兩下智慧ID
標記中的 [設定資料源] 連結。 從 [數據源設定精靈] 選擇新增資料源。
圖 1:為 DropDownList 新增數據源 (按兩下即可檢視完整大小的影像)
新的數據源自然應該是 ObjectDataSource。 將此新的 ObjectDataSource CategoriesDataSource
命名為 ,並讓它叫 CategoriesBLL
用物件的 GetCategories()
方法。
圖 2:選擇使用 CategoriesBLL
類別 (按鍵即可檢視完整大小的影像)
圖 3:將 ObjectDataSource 設定為使用 GetCategories()
方法 (按兩下即可檢視完整大小的影像)
設定 ObjectDataSource 之後,我們仍然需要指定應該顯示在 DropDownList 中的 Categories
數據源欄位,以及哪一個字段應該設定為清單專案的值。 將 CategoryName
欄位設定為顯示,並 CategoryID
設定為每個清單專案的值。
圖 4:讓 DropDownList 顯示 CategoryName
欄位並使用 CategoryID
作為值 (按兩下即可檢視大小完整的影像)
此時,我們有DropDownList控件 (Categories
) ,而該控件會填入數據表中的 Categories
記錄。 當使用者從DropDownList選擇新的類別時,我們想要進行回傳,以重新整理我們將在步驟 2 中建立的產品DropDownList。 因此,從 categories
DropDownList的智慧標記中檢查 [啟用 AutoPostBack] 選項。
圖 5:為 DropDownList 啟用 AutoPostBack Categories
(按兩下即可檢視完整大小的影像)
步驟 2:在第二個 DropDownList 中顯示選取類別的產品
完成 Categories
DropDownList之後,下一個步驟是顯示屬於所選類別的產品DropDownList。 若要完成此作業,請將另一個DropDownList新增至名為 ProductsByCategory
的頁面。 Categories
如同 DropDownList,為名為 ProductsByCategoryDataSource
的 ProductsByCategory
DropDownList 建立新的 ObjectDataSource。
圖 6:為 DropDownList 新增數據源 ProductsByCategory
(按兩下即可檢視大小完整的影像)
圖 7:建立名為 ProductsByCategoryDataSource
的新 ObjectDataSource (按兩下即可檢視完整大小的影像)
ProductsByCategory
由於DropDownList只需要顯示屬於所選類別的這些產品,因此 ObjectDataSource 會從 ProductsBLL
物件叫GetProductsByCategoryID(categoryID)
用 方法。
圖 8:選擇使用 ProductsBLL
類別 (按鍵即可檢視完整大小的影像)
圖 9:將 ObjectDataSource 設定為使用 GetProductsByCategoryID(categoryID)
方法 (按兩下即可檢視全大小影像)
在精靈的最後一個步驟中,我們需要指定 參數的值 categoryID
。 從 Categories
DropDownList將此參數指派給選取的專案。
圖 10:從 Categories
DropDownList 提取categoryID
參數值 (按兩下即可檢視完整大小的影像)
設定 ObjectDataSource 後,所有保留專案都是指定用於DropDownList項目顯示和值的數據源字段。 ProductName
顯示欄位,並使用 ProductID
欄位作為值。
圖 11:指定 DropDownList 的 ListItem
Text
[數據源欄位] 和 Value
[屬性] (按兩下即可檢視完整大小的影像)
設定 ObjectDataSource 和 ProductsByCategory
DropDownList 後,我們的頁面會顯示兩個 DropDownList:第一個會列出所有類別,而第二個則會列出屬於所選類別的產品。 當使用者從第一個DropDownList中選取新的類別時,會加入回傳,而第二個DropDownList將會重新系結,顯示屬於新選取類別的產品。 圖 12 和 13 會在透過瀏覽器檢視時顯示 MasterDetailsDetails.aspx
作用中。
圖 12:第一次瀏覽頁面時,已選取 [篩選類別] (按兩下即可檢視完整大小的影像)
圖 13:選擇不同的類別顯示新類別的產品, (按兩下即可檢視完整大小的影像)
目前DropDownList在 productsByCategory
變更時 ,不會 造成回傳。 不過,一旦新增 DetailsView 以顯示所選產品的詳細數據, (步驟 3) ,就會想要進行回傳。 因此,從 productsByCategory
DropDownList的智慧標記中選取 [啟用 AutoPostBack] 複選框。
圖 14:啟用DropDownList的 productsByCategory
AutoPostBack 功能 (按兩下即可檢視完整大小的影像)
步驟 3:使用 DetailsView 顯示所選產品的詳細數據
最後一個步驟是在 DetailsView 中顯示所選產品的詳細數據。 若要達成此目的,請將DetailsView新增至頁面、將其 ID
屬性設定為 ProductDetails
,併為其建立新的 ObjectDataSource。 將這個 ObjectDataSource 設定為使用DropDownList的選取值,從 ProductsBLL
類別的 GetProductByProductID(productID)
方法提取其數據,以取得 參數的值productID
。ProductsByCategory
圖 15:選擇使用 ProductsBLL
類別 (按下即可檢視完整大小的影像)
圖 16:將 ObjectDataSource 設定為使用 GetProductByProductID(productID)
方法 (按兩下即可檢視完整大小的影像)
圖 17:從 ProductsByCategory
DropDownList 提取productID
參數值 (按兩下即可檢視大小完整的影像)
您可以選擇在 DetailsView 中 ProductDetails
顯示任何可用的欄位。 我選擇移除 ProductID
、 SupplierID
和 CategoryID
欄位,並重新排序並格式化其餘欄位。 此外,我清除了 DetailsView 的 Height
和 Width
屬性,讓 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 所示。
圖 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的值已變更時,ProductDetails
DetailsView 的 ObjectDataSource 已經完成其參數值檢查;因此,DetailsView 會顯示其先前的結果。 此互動描述於圖 20 中。
圖 20: ProductsByCategory
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 強調此變更如何解決先前的問題。
圖 21:ProductDetails
當 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放在 。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應