Share via


Filtern von Master-/Detailberichten mit zwei DropDownList-Steuerelementen (C#)

von Scott Mitchell

PDF herunterladen

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 CustomersTabellen , Ordersund 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 Categoriesfest, 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.

Hinzufügen einer neuen Datenquelle für dropDownList

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.

Wählen Sie aus, um die CategoriesBLL-Klasse zu verwenden.

Abbildung 2: Auswählen der Verwendung der CategoriesBLL -Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Konfigurieren der ObjectDataSource für die Verwendung der GetCategories()-Methode

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.

Lassen Sie die DropDownList das Feld CategoryName anzeigen und CategoryID als Wert verwenden.

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.

Aktivieren von AutoPostBack für die Kategorien 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 ProductsByCategoryhinzu. Erstellen Sie wie bei DropDownList Categories eine neue ObjectDataSource für die DropDownList mit dem ProductsByCategory Namen ProductsByCategoryDataSource.

Hinzufügen einer neuen Datenquelle für die Dropdownliste

Abbildung 6: Hinzufügen einer neuen Datenquelle für die ProductsByCategory DropDownList (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Erstellen einer neuen ObjectDataSource namens ProductsByCategoryDataSource

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.

Screenshot: Fenster

Abbildung 8: Auswählen der Verwendung der ProductsBLL -Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Konfigurieren der ObjectDataSource für die Verwendung der GetProductsByCategoryID(categoryID)-Methode

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.

Pullen des categoryID-Parameterwerts aus der Kategorien-Dropdownliste

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.

Angeben der Datenquellenfelder, die für die Text- und Werteigenschaften von ListItems verwendet werden

Abbildung 11: Angeben der Datenquellenfelder, die für die Eigenschaften und Value der DropDownList ListItemText 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.

Beim ersten Besuch der Seite wird die Kategorie

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)

Wenn Sie eine andere Kategorie auswählen, werden die Produkte der neuen Kategorie angezeigt.

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.

Aktivieren des AutoPostBack-Features für die DropDownList productsByCategory

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 ProductDetailsfest, 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.

Screenshot des Fensters Datenquelle konfigurieren – productsByCategoryDataSource, in dem ProductsBLL ausgewählt und die Schaltfläche Weiter hervorgehoben ist.

Abbildung 15: Auswählen der Verwendung der ProductsBLL -Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Konfigurieren der ObjectDataSource für die Verwendung der GetProductByProductID(productID)-Methode

Abbildung 16: Konfigurieren der ObjectDataSource für die Verwendung der GetProductByProductID(productID) -Methode (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Pullen des productID-Parameterwerts aus der DropDownList für ProductsByCategory

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 Detailansicht anzeigen. Ich habe mich dafür entschieden, die ProductIDFelder , SupplierIDund 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.

Die Details des ausgewählten Produkts werden in einer Detailansicht angezeigt.

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.

Die Details des zuvor ausgewählten Produkts werden weiterhin angezeigt.

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.

Der ProductsByCategory DropDownList-Wert ändert sich nach der ObjectDataSource-Überprüfung von ProductDetails DetailsView auf Änderungen.

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 void ProductsByCategory_DataBound(object sender, EventArgs e)
{
    ProductDetails.DataBind();
}

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.

ProductDetails DetailsView wird explizit aktualisiert, wenn das DataBound-Ereignis der ProductsByCategory DropDownList ausgelöst wird.

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.