Filtern von Master-/Detailberichten mit zwei DropDownList-Steuerelementen (VB)
von Scott Mitchell
In diesem Tutorial wird die master-Detail-Beziehung erweitert, um eine dritte Ebene hinzuzufügen, indem zwei DropDownList-Steuerelemente verwendet werden, um die gewünschten übergeordneten und großelternseitigen Datensätze auszuwählen.
Einführung
Im vorherigen Tutorial haben wir untersucht, wie Sie einen einfachen master/Details-Bericht mithilfe einer einzelnen DropDownList mit den Kategorien und einer GridView mit den Produkten anzeigen, die zur ausgewählten Kategorie gehören. Dieses Berichtsmuster funktioniert gut beim Anzeigen von Datensätzen, die eine 1:n-Beziehung aufweisen, und kann problemlos erweitert werden, um für Szenarien zu funktionieren, die mehrere 1:n-Beziehungen enthalten. Beispielsweise verfügt ein Bestellerfassungssystem über Tabellen, die Kunden, Bestellungen und Bestellpositionen entsprechen. Ein bestimmter Kunde kann mehrere Bestellungen haben, wobei jede Bestellung aus mehreren Artikeln besteht. Solche Daten können dem Benutzer mit zwei DropDownLists und einem GridView-Objekt angezeigt werden. Die erste DropDownList enthält ein Listenelement für jeden Kunden in der Datenbank, wobei der Inhalt des zweiten die Vom ausgewählten Kunden aufgegebenen Bestellungen ist. Eine GridView listet die Positionen aus der ausgewählten Reihenfolge auf.
Obwohl die Northwind-Datenbank die kanonischen Kunden-/Bestell-/Bestelldetails in den Customers
Tabellen , Orders
und Order Details
enthält, werden diese Tabellen nicht in unserer Architektur erfasst. Dennoch können wir die Verwendung von zwei abhängigen DropDownLists veranschaulichen. Die erste DropDownList listet die Kategorien und die zweite die Produkte auf, die zur ausgewählten Kategorie gehören. Eine DetailsView listet dann die Details des ausgewählten Produkts auf.
Schritt 1: Erstellen und Auffüllen der Kategorien DropDownList
Unser erstes Ziel ist es, die DropDownList hinzuzufügen, die die Kategorien auflistet. Diese Schritte wurden im vorherigen Tutorial ausführlich untersucht, sind aber hier auf Vollständigkeit zusammengefasst.
Öffnen Sie die MasterDetailsDetails.aspx
Seite im Filtering
Ordner, fügen Sie der Seite eine DropDownList hinzu, legen Sie deren ID
Eigenschaft auf Categories
fest, und klicken Sie dann im Smarttag auf den Link Datenquelle konfigurieren. Wählen Sie im Assistenten für die Datenquellenkonfiguration aus, um eine neue Datenquelle hinzuzufügen.
Abbildung 1: Hinzufügen einer neuen Datenquelle für die DropDownList (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Die neue Datenquelle sollte natürlich eine ObjectDataSource sein. Nennen Sie diese neue ObjectDataSource CategoriesDataSource
, und lassen Sie die CategoriesBLL
-Methode des GetCategories()
Objekts aufrufen.
Abbildung 2: Auswählen der Verwendung der CategoriesBLL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 3: Konfigurieren der ObjectDataSource für die Verwendung der GetCategories()
-Methode (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nach dem Konfigurieren der ObjectDataSource müssen wir weiterhin angeben, welches Datenquellenfeld in der Categories
DropDownList angezeigt werden soll und welches als Wert für das Listenelement konfiguriert werden soll. Legen Sie das CategoryName
Feld als Anzeige und CategoryID
als Wert für jedes Listenelement fest.
Abbildung 4: DropDownList zeigt das CategoryName
Feld an und Verwenden als CategoryID
Wert (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
An diesem Punkt verfügen wir über ein DropDownList-Steuerelement (Categories
), das mit den Datensätzen aus der Categories
Tabelle aufgefüllt wird. Wenn der Benutzer eine neue Kategorie aus der DropDownList auswäht, soll ein Postback erfolgen, um das Produkt DropDownList zu aktualisieren, das wir in Schritt 2 erstellen. Aktivieren Sie daher die Option AutoPostBack aktivieren im categories
Smarttag von DropDownList.
Abbildung 5: Aktivieren von AutoPostBack für dropDownList Categories
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Schritt 2: Anzeigen der Produkte der ausgewählten Kategorie in einer zweiten DropDownList
Nachdem die Categories
DropDownList abgeschlossen ist, besteht unser nächster Schritt darin, eine DropDownList der Produkte anzuzeigen, die zur ausgewählten Kategorie gehören. Um dies zu erreichen, fügen Sie der Seite eine weitere DropDownList mit dem Namen ProductsByCategory
hinzu. Erstellen Sie wie bei DropDownList Categories
eine neue ObjectDataSource für die DropDownList mit dem ProductsByCategory
Namen ProductsByCategoryDataSource
.
Abbildung 6: Hinzufügen einer neuen Datenquelle für die ProductsByCategory
DropDownList (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 7: Erstellen einer neuen ObjectDataSource namens ProductsByCategoryDataSource
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Da die ProductsByCategory
DropDownList nur die Produkte anzeigen muss, die zur ausgewählten Kategorie gehören, lassen Sie die ObjectDataSource die GetProductsByCategoryID(categoryID)
-Methode aus dem ProductsBLL
-Objekt aufrufen.
Abbildung 8: Auswählen der Verwendung der ProductsBLL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 9: Konfigurieren der ObjectDataSource für die Verwendung der GetProductsByCategoryID(categoryID)
-Methode (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Im letzten Schritt des Assistenten müssen wir den Wert des categoryID
Parameters angeben. Weisen Sie diesen Parameter dem ausgewählten Element aus der Categories
DropDownList zu.
Abbildung 10: Pull the categoryID
Parameter Value from the Categories
DropDownList (Click to view full-size image)
Wenn objectDataSource konfiguriert ist, bleibt nur anzugeben, welche Datenquellenfelder für die Anzeige und den Wert der DropDownList-Elemente verwendet werden. Zeigen Sie das ProductName
Feld an, und verwenden Sie das ProductID
Feld als Wert.
Abbildung 11: Angeben der Datenquellenfelder, die für die Eigenschaften und Value
der DropDownList ListItem
Text
verwendet werden (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Wenn ObjectDataSource und ProductsByCategory
DropDownList konfiguriert sind, werden auf unserer Seite zwei DropDownLists angezeigt: Die erste Liste listet alle Kategorien auf, während die zweite listet die Produkte auf, die zur ausgewählten Kategorie gehören. Wenn der Benutzer eine neue Kategorie aus der ersten DropDownList auswählt, wird ein Postback ausgeführt, und die zweite DropDownList wird erneut gesendet, wobei die Produkte angezeigt werden, die zur neu ausgewählten Kategorie gehören. Die Abbildungen 12 und 13 zeigen MasterDetailsDetails.aspx
in Aktion, wenn sie über einen Browser angezeigt werden.
Abbildung 12: Beim ersten Besuch der Seite ist die Kategorie "Getränke" ausgewählt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 13: Auswählen einer anderen Kategorie zeigt die Produkte der neuen Kategorie an (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Derzeit verursacht die productsByCategory
DropDownList, wenn sie geändert wird, kein Postback. Wir möchten jedoch, dass ein Postback erfolgt, nachdem wir eine DetailsView hinzugefügt haben, um die Details des ausgewählten Produkts anzuzeigen (Schritt 3). Aktivieren Sie daher das Kontrollkästchen AutoPostBack aktivieren im Smarttag von productsByCategory
DropDownList.
Abbildung 14: Aktivieren des AutoPostBack-Features für dropDownList productsByCategory
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Schritt 3: Verwenden einer Detailansicht zum Anzeigen von Details für das ausgewählte Produkt
Der letzte Schritt besteht darin, die Details für das ausgewählte Produkt in einer Detailansicht anzuzeigen. Um dies zu erreichen, fügen Sie der Seite ein DetailsView-Element hinzu, legen Sie die ID
-Eigenschaft auf ProductDetails
fest, und erstellen Sie eine neue ObjectDataSource dafür. Konfigurieren Sie diese ObjectDataSource, um die Daten aus der -Methode der ProductsBLL
-Klasse GetProductByProductID(productID)
mithilfe des ausgewählten Werts von ProductsByCategory
DropDownList für den Wert des productID
Parameters abzurufen.
Abbildung 15: Auswählen der Verwendung der ProductsBLL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 16: Konfigurieren der ObjectDataSource für die Verwendung der GetProductByProductID(productID)
-Methode (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 17: Pull the productID
Parameter Value from the ProductsByCategory
DropDownList (Click to view full-size image)
Sie können eines der verfügbaren Felder in der ProductDetails
Detailansicht anzeigen. Ich habe mich dafür entschieden, die ProductID
Felder , SupplierID
und zu entfernen, und CategoryID
die übrigen Felder neu angeordnet und formatiert. Darüber hinaus habe ich die Eigenschaften von DetailsView Height
und Width
gelöscht, sodass DetailsView auf die Breite erweitert werden kann, die erforderlich ist, um die Daten optimal anzuzeigen, anstatt sie auf eine angegebene Größe zu beschränken. Das vollständige Markup wird unten angezeigt:
<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>
Nehmen Sie sich einen Moment Zeit, um die MasterDetailsDetails.aspx
Seite in einem Browser auszuprobieren. Auf den ersten Blick mag es scheinen, dass alles wie gewünscht funktioniert, aber es gibt ein subtiles Problem. Wenn Sie eine neue Kategorie auswählen, wird die ProductsByCategory
DropDownList aktualisiert, um diese Produkte für die ausgewählte Kategorie einzuschließen, aber die ProductDetails
DetailsView zeigt weiterhin die vorherigen Produktinformationen an. Die DetailsView wird aktualisiert, wenn Sie ein anderes Produkt für die ausgewählte Kategorie auswählen. Wenn Sie gründlich genug testen, werden Sie außerdem feststellen, dass, wenn Sie ständig neue Kategorien auswählen (z. B. Getränke aus der Categories
DropDownList, dann Condiments, dann Confections) jede andere Kategorieauswahl dazu führt, dass die ProductDetails
DetailAnsicht aktualisiert wird.
Um dieses Problem zu konkretisieren, sehen wir uns ein bestimmtes Beispiel an. Wenn Sie die Seite zum ersten Mal besuchen, wird die Kategorie Getränke ausgewählt, und die zugehörigen Produkte werden in die ProductsByCategory
DropDownList geladen. Chai ist das ausgewählte Produkt, und seine Details werden in der ProductDetails
Detailansicht angezeigt, wie in Abbildung 18 dargestellt.
Abbildung 18: Die Details des ausgewählten Produkts werden in einer Detailansicht angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Wenn Sie die Kategorieauswahl von Beverages in Condiments ändern, erfolgt ein Postback, und die ProductsByCategory
DropDownList wird entsprechend aktualisiert, aber detailsView zeigt weiterhin Details für Chai an.
Abbildung 19: Die Details des zuvor ausgewählten Produkts werden weiterhin angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Wenn Sie ein neues Produkt aus der Liste auswählen, wird die DetailsView wie erwartet aktualisiert. Wenn Sie nach dem Ändern des Produkts eine neue Kategorie auswählen, wird die DetailsView erneut nicht aktualisiert. Wenn Sie jedoch anstelle eines neuen Produkts eine neue Kategorie ausgewählt haben, würde die DetailsView aktualisiert. Was in der Welt ist hier los?
Das Problem ist ein Zeitsteuerungsproblem im Lebenszyklus der Seite. Jedes Mal, wenn eine Seite angefordert wird, führt sie eine Reihe von Schritten als Rendering durch. In einem dieser Schritte überprüfen die ObjectDataSource-Steuerelemente, ob sich ihre SelectParameters
Werte geändert haben. Wenn ja, weiß das an objectDataSource gebundene Datenwebsteuerelement, dass es seine Anzeige aktualisieren muss. Wenn z. B. eine neue Kategorie ausgewählt wird, erkennt ObjectDataSource ProductsByCategoryDataSource
, dass sich die Parameterwerte geändert haben, und die ProductsByCategory
DropDownList wird neu gebunden, sodass die Produkte für die ausgewählte Kategorie abgerufen werden.
Das Problem, das in dieser Situation auftritt, besteht darin, dass der Punkt im Seitenlebenszyklus, den objectDataSources auf geänderte Parameter überprüft, vor der Neubindung der zugeordneten Datenwebsteuerelemente auftritt. Daher erkennt die ProductsByCategoryDataSource
ObjectDataSource beim Auswählen einer neuen Kategorie eine Änderung im Wert des Parameters. Die von DetailsView ProductDetails
verwendete ObjectDataSource weist jedoch keine derartigen Änderungen auf, da die ProductsByCategory
DropDownList noch nicht rebound ausgeführt werden muss. Später im Lebenszyklus wird die ProductsByCategory
DropDownList erneut an ihre ObjectDataSource gebunden, wobei die Produkte für die neu ausgewählte Kategorie abgerufen werden. Während sich der Wert der ProductsByCategory
DropDownList geändert hat, hat die ObjectDataSource von ProductDetails
DetailsView bereits ihre Parameterwertüberprüfung durchgeführt. Daher zeigt die DetailsView die vorherigen Ergebnisse an. Diese Interaktion ist in Abbildung 20 dargestellt.
Abbildung 20: Der ProductsByCategory
DropDownList-Wert ändert sich nach der ProductDetails
ObjectDataSource-Überprüfung von DetailsView auf Änderungen (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Um dies zu beheben, müssen wir detailsView ProductDetails
explizit neu binden, nachdem die ProductsByCategory
DropDownList gebunden wurde. Sie können dies erreichen, indem Sie die ProductDetails
Methode von DataBind()
DetailsView aufrufen, wenn das ProductsByCategory
DropDownList-Ereignis DataBound
ausgelöst wird. Fügen Sie der CodeBehind-Klasse der Seite den MasterDetailsDetails.aspx
folgenden Ereignishandlercode hinzu (eine Erläuterung zum Hinzufügen eines Ereignishandlers finden Sie unter "Programmgesteuertes Festlegen der Parameterwerte der ObjectDataSource"):
Protected Sub ProductsByCategory_DataBound(sender As Object, e As EventArgs) _
Handles ProductsByCategory.DataBound
ProductDetails.DataBind()
End Sub
Nachdem dieser explizite Aufruf der Methode von ProductDetails
DetailsView DataBind()
hinzugefügt wurde, funktioniert das Tutorial wie erwartet. Abbildung 21 zeigt, wie sich das frühere Problem dadurch geändert hat.
Abbildung 21: DetailsView ProductDetails
wird explizit aktualisiert, wenn das Ereignis der ProductsByCategory
DropDownList DataBound
ausgelöst wird (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Zusammenfassung
DropDownList dient als ideales Benutzeroberflächenelement für master-/Detailberichte, bei denen eine 1:n-Beziehung zwischen den master und Detaildatensätzen besteht. Im vorherigen Tutorial haben wir erfahren, wie Sie eine einzelne DropDownList verwenden, um die nach der ausgewählten Kategorie angezeigten Produkte zu filtern. In diesem Tutorial haben wir die GridView von Produkten durch eine DropDownList ersetzt und eine DetailsView verwendet, um die Details des ausgewählten Produkts anzuzeigen. Die in diesem Tutorial erläuterten Konzepte können problemlos auf Datenmodelle erweitert werden, die mehrere 1:n-Beziehungen wie Kunden, Bestellungen und Bestellelemente umfassen. Im Allgemeinen können Sie immer eine DropDownList für jede der "1"-Entitäten in den 1:n-Beziehungen hinzufügen.
Viel Spaß beim Programmieren!
Zum Autor
Scott Mitchell, Autor von sieben ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.
Besonderer Dank an
Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Leitender Prüfer für dieses Tutorial war Hilton Giesenow. Möchten Sie meine bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für