Master-/Detailbericht mit einer Aufzählung der Masterdatensätze und einem DataList-Steuerelement für die Details (C#)
von Scott Mitchell
In diesem Tutorial komprimieren wir den zweiseitigen master/Detailbericht des vorherigen Tutorials auf eine einzelne Seite, in der eine Aufzählungsliste mit Kategorienamen auf der linken Seite des Bildschirms und die Produkte der ausgewählten Kategorie auf der rechten Seite des Bildschirms angezeigt werden.
Einführung
Im vorherigen Tutorial haben wir uns mit der Trennung eines master-/Detailberichts auf zwei Seiten befasst. Auf der Seite master haben wir ein Repeater-Steuerelement verwendet, um eine Aufzählung von Kategorien zu rendern. Jeder Kategoriename war ein Link, der den Benutzer beim Klicken zur Detailseite führte, auf der eine zweispaltige DataList die Produkte anzeigte, die zur ausgewählten Kategorie gehören.
In diesem Tutorial komprimieren wir das zweiseitige Tutorial in eine einzelne Seite, wobei eine Aufzählungsliste mit Kategorienamen auf der linken Seite des Bildschirms angezeigt wird, wobei jeder Kategoriename als LinkButton gerendert wird. Durch Klicken auf einen der Kategorienamen LinkButtons wird ein Postback ausgelöst und die produkte der ausgewählten Kategorie an eine zweispaltige DataList auf der rechten Seite des Bildschirms gebunden. Neben dem Namen der einzelnen Kategorien zeigt der Repeater auf der linken Seite an, wie viele Produkte insgesamt für eine bestimmte Kategorie vorhanden sind (siehe Abbildung 1).
Abbildung 1: Der Name der Kategorie und die Gesamtanzahl der Produkte werden auf der linken Seite angezeigt (Klicken Sie, um das vollständige Bild anzuzeigen)
Schritt 1: Anzeigen eines Repeaters im linken Bereich des Bildschirms
Für dieses Tutorial muss links neben den Produkten der ausgewählten Kategorie die Aufzählungsliste der Kategorien angezeigt werden. Inhalte auf einer Webseite können mithilfe von Standard-HTML-Element-Absatztags, nicht brechenden Leerzeichen, <table>
s usw. oder mithilfe von CSS-Techniken (Cascading Stylesheet) positioniert werden. Alle unsere Tutorials haben bisher CSS-Techniken für die Positionierung verwendet. Als wir die Navigationsbenutzeroberfläche in unserer master Seite im Tutorial Gestaltungsseiten und Websitenavigation erstellt haben, haben wir die absolute Positionierung verwendet, um den präzisen Pixeloffset für die Navigationsliste und den Standard Inhalt anzugeben. Alternativ kann CSS verwendet werden, um ein Element rechts oder links von einem anderen durch Floating zu positionieren. Wir können die Aufzählungsliste der Kategorien links neben den ausgewählten Produkten der Kategorie anzeigen lassen, indem der Repeater links neben der DataList angezeigt wird.
Öffnen Sie die CategoriesAndProducts.aspx
Seite aus dem DataListRepeaterFiltering
Ordner, und fügen Sie der Seite einen Repeater und eine DataList hinzu. Legen Sie den Repeater s ID
auf Categories
und die DataList s auf fest CategoryProducts
. Wechseln Sie zur Quellansicht, und fügen Sie die Steuerelemente Repeater und DataList in ihre eigenen <div>
Elemente ein. Das heißt, schließen Sie zuerst den Repeater in ein <div>
-Element und dann die DataList in ein eigenes <div>
Element direkt nach dem Repeater ein. Ihr Markup sollte an dieser Stelle wie folgt aussehen:
<div>
<asp:Repeater ID="Categories" runat="server">
</asp:Repeater>
</div>
<div>
<asp:DataList ID="CategoryProducts" runat="server">
</asp:DataList>
</div>
Um den Repeater links neben der DataList zu verschieben, müssen wir das float
CSS-Formatattribut wie folgt verwenden:
<div>
Repeater
</div>
<div>
DataList
</div>
Die float: left;
schwebt das erste <div>
Element links vom zweiten Element. Die width
Einstellungen und padding-right
geben die ersten <div>
s width
an und wie viel Abstand zwischen dem Inhalt des <div>
Elements und dem rechten Rand hinzugefügt wird. Weitere Informationen zu schwebenden Elementen in CSS finden Sie unter Floatutorial.
Anstatt die Stileinstellung direkt über das Attribut des ersten <p>
Elements anzugeben style
, erstellen sie stattdessen eine neue CSS-Klasse mit Styles.css
dem Namen FloatLeft
:
.FloatLeft
{
float: left;
width: 33%;
padding-right: 10px;
}
Dann können sie durch <div class="FloatLeft">
ersetzen<div>
.
Nachdem Sie die CSS-Klasse hinzugefügt und das Markup auf der CategoriesAndProducts.aspx
Seite konfiguriert haben, wechseln Sie zum Designer. Sie sollten den Repeater links neben der DataList sehen (obwohl beide im Moment nur als graue Felder angezeigt werden, da wir ihre Datenquellen oder Vorlagen noch nicht konfigurieren müssen).
Abbildung 2: Der Repeater wird links von der DataList angezeigt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Schritt 2: Bestimmen der Anzahl der Produkte für jede Kategorie
Nachdem das umgebende Markup für Repeater und DataList abgeschlossen ist, können wir die Kategoriedaten an das Repeater-Steuerelement binden. Wie jedoch die Aufzählung der Kategorien in Abbildung 1 zeigt, müssen wir zusätzlich zum Namen jeder Kategorie auch die Anzahl der produkte anzeigen, die der Kategorie zugeordnet sind. Um auf diese Informationen zuzugreifen, können wir entweder:
- Ermitteln Sie diese Informationen aus der CodeBehind-Klasse der ASP.NET Seite. Bei einem bestimmten Wert
categoryID
können wir die Anzahl der zugeordneten Produkte bestimmen, indem wir dieProductsBLL
Methode der Klasse sGetProductsByCategoryID(categoryID)
aufrufen. Diese Methode gibt einProductsDataTable
-Objekt zurück, dessenCount
Eigenschaft angibt, wie vieleProductsRow
s vorhanden sind. Dies ist die Anzahl der Produkte für das angegebenecategoryID
. Wir können einenItemDataBound
Ereignishandler für den Repeater erstellen, der für jede kategorie, die an den Repeater gebunden ist, dieProductsBLL
Klasse s-MethodeGetProductsByCategoryID(categoryID)
aufruft und deren Anzahl in die Ausgabe einschließt. - Aktualisieren Sie den
CategoriesDataTable
im Typisierten DataSet, um eineNumberOfProducts
Spalte einzuschließen. Wir können dann dieGetCategories()
-Methode inCategoriesDataTable
aktualisieren, um diese Informationen einzuschließen, oder alternativ unverändert lassenGetCategories()
und eine neueCategoriesDataTable
Methode mit dem NamenGetCategoriesAndNumberOfProducts()
erstellen.
Lassen Sie uns beide Techniken untersuchen. Der erste Ansatz ist einfacher zu implementieren, da die Datenzugriffsebene nicht aktualisiert werden muss. Dies erfordert jedoch mehr Kommunikation mit der Datenbank. Der Aufruf der ProductsBLL
Klasse s-Methode GetProductsByCategoryID(categoryID)
im ItemDataBound
Ereignishandler fügt einen zusätzlichen Datenbankaufruf für jede kategorie hinzu, die im Repeater angezeigt wird. Bei diesem Verfahren gibt es N + 1 Datenbankaufrufe, wobei N die Anzahl der im Repeater angezeigten Kategorien ist. Beim zweiten Ansatz wird die Produktanzahl mit Informationen zu jeder Kategorie aus der Methode der CategoriesBLL
Klasse s GetCategories()
(oder GetCategoriesAndNumberOfProducts()
) zurückgegeben, was zu nur einem Trip zur Datenbank führt.
Ermitteln der Anzahl von Produkten im ItemDataBound-Ereignishandler
Die Bestimmung der Anzahl von Produkten für jede Kategorie im Repeater-Ereignishandler ItemDataBound
erfordert keine Änderungen an unserer vorhandenen Datenzugriffsebene. Alle Änderungen können direkt auf der CategoriesAndProducts.aspx
Seite vorgenommen werden. Fügen Sie zunächst eine neue ObjectDataSource mit dem Namen über CategoriesDataSource
das Smarttag des Repeaters hinzu. Konfigurieren Sie als Nächstes die CategoriesDataSource
ObjectDataSource so, dass sie ihre Daten aus der Methode der CategoriesBLL
Klasse s abruft GetCategories()
.
Abbildung 3: Konfigurieren der ObjectDataSource für die Verwendung der Methode der CategoriesBLL
GetCategories()
Klasse (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Jedes Element im Categories
Repeater muss angeklickt werden können, und wenn darauf geklickt wird, wird die CategoryProducts
DataList dazu führen, dass diese Produkte für die ausgewählte Kategorie angezeigt werden. Dies kann erreicht werden, indem Sie jede Kategorie zu einem Hyperlink machen und eine Verknüpfung mit derselben Seite (CategoriesAndProducts.aspx
) herstellen, aber die CategoryID
Abfragezeichenfolge durchgibt, ähnlich wie im vorherigen Tutorial. Der Vorteil dieses Ansatzes besteht darin, dass eine Seite, die Produkte einer bestimmten Kategorie anzeigt, von einer Suchmaschine als Lesezeichen und indiziert werden kann.
Alternativ können wir jede Kategorie als LinkButton festlegen. Dies ist der Ansatz, den wir für dieses Tutorial verwenden. Der LinkButton wird im Browser des Benutzers als Link gerendert, löst jedoch beim Klicken ein Postback aus. beim Postback muss die DataList-ObjektDataSource aktualisiert werden, um die Produkte anzuzeigen, die zur ausgewählten Kategorie gehören. In diesem Tutorial ist die Verwendung eines Links sinnvoller als die Verwendung eines LinkButton. es kann jedoch auch andere Szenarien geben, in denen die Verwendung eines LinkButton-Steuerelements vorteilhafter ist. Während der Hyperlinkansatz für dieses Beispiel ideal wäre, lassen Sie uns stattdessen die Verwendung von LinkButton untersuchen. Wie wir sehen werden, bringt die Verwendung eines LinkButton einige Herausforderungen mit sich, die andernfalls bei einem Link nicht auftreten würden. Daher werden durch die Verwendung eines LinkButton in diesem Tutorial diese Herausforderungen hervorgehoben und Lösungen für die Szenarien bereitgestellt, in denen wir möglicherweise einen LinkButton anstelle eines Hyperlinks verwenden möchten.
Hinweis
Es wird empfohlen, dieses Tutorial mit einem HyperLink-Steuerelement oder <a>
-Element anstelle von LinkButton zu wiederholen.
Das folgende Markup zeigt die deklarative Syntax für den Repeater und die ObjectDataSource. Beachten Sie, dass die Vorlagen des Repeaters eine Aufzählung mit jedem Element als LinkButton rendern:
<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:LinkButton runat="server" ID="ViewCategory" /></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
Hinweis
Für dieses Tutorial muss der Ansichtszustand für den Repeater aktiviert sein (beachten Sie die Auslassung von der EnableViewState="False"
deklarativen Syntax des Repeaters). In Schritt 3 erstellen wir einen Ereignishandler für das Repeater-Ereignis ItemCommand
, in dem wir die DataList s ObjectDataSource-Auflistung SelectParameters
aktualisieren. Der Repeater wird jedoch nicht ausgelöst, wenn der Ansichtszustand ItemCommand
deaktiviert ist.
Für linkButton mit dem ID
Eigenschaftswert von ViewCategory
ist seine Text
Eigenschaft nicht festgelegt. Wenn wir nur den Kategorienamen anzeigen wollten, hätten wir die Text-Eigenschaft deklarativ über die Datenbindungssyntax wie folgt festgelegt:
<asp:LinkButton runat="server" ID="ViewCategory"
Text='<%# Eval("CategoryName") %>' />
Wir möchten jedoch sowohl den Namen der Kategorie als auch die Anzahl der Produkte anzeigen, die zu dieser Kategorie gehören. Diese Informationen können aus dem Repeater-Ereignishandler ItemDataBound
abgerufen werden, indem Sie die Methode der ProductBLL
Klasse s GetCategoriesByProductID(categoryID)
aufrufen und bestimmen, wie viele Datensätze im resultierenden ProductsDataTable
zurückgegeben werden, wie der folgende Code veranschaulicht:
protected void Categories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// Make sure we're working with a data item...
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Reference the CategoriesRow instance bound to this RepeaterItem
Northwind.CategoriesRow category =
(Northwind.CategoriesRow) ((System.Data.DataRowView) e.Item.DataItem).Row;
// Determine how many products are in this category
NorthwindTableAdapters.ProductsTableAdapter productsAPI =
new NorthwindTableAdapters.ProductsTableAdapter();
int productCount =
productsAPI.GetProductsByCategoryID(category.CategoryID).Count;
// Reference the ViewCategory LinkButton and set its Text property
LinkButton ViewCategory = (LinkButton)e.Item.FindControl("ViewCategory");
ViewCategory.Text =
string.Format("{0} ({1:N0})", category.CategoryName, productCount);
}
}
Zunächst stellen wir sicher, dass wir mit einem Datenelement arbeiten (eines, dessen ItemType
oder istItem
) AlternatingItem
und dann auf die CategoriesRow
instance verweisen, die gerade an das aktuelle RepeaterItem
gebunden wurde. Als Nächstes bestimmen wir die Anzahl der Produkte für diese Kategorie, indem wir eine instance der -Klasse erstellen, ihre ProductsBLL
GetCategoriesByProductID(categoryID)
Methode aufrufen und die Anzahl der mit der Count
-Eigenschaft zurückgegebenen Datensätze ermitteln. Schließlich ist der ViewCategory
LinkButton in der ItemTemplate Verweise, und seine Text
Eigenschaft ist auf CategoryName (NumberOfProductsInCategory) festgelegt, wobei NumberOfProductsInCategory als Zahl mit null Dezimalstellen formatiert ist.
Hinweis
Alternativ hätten wir der CodeBehind-Klasse der ASP.NET Seite eine Formatierungsfunktion hinzugefügt, die eine Kategorie s CategoryName
und Werte akzeptiert und CategoryID
die CategoryName
mit der Anzahl der Produkte in der Kategorie verkettet zurückgibt (wie durch aufrufen der GetCategoriesByProductID(categoryID)
-Methode ermittelt). Die Ergebnisse einer solchen Formatierungsfunktion könnten deklarativ der Text-Eigenschaft von LinkButton zugewiesen werden, wodurch die Notwendigkeit des ItemDataBound
Ereignishandlers ersetzt wird. Weitere Informationen zur Verwendung von Formatierungsfunktionen finden Sie in den Tutorials Verwenden von TemplateFields im GridView-Steuerelement oder Formatieren von DataList und Repeater basierend auf Daten .
Nehmen Sie sich nach dem Hinzufügen dieses Ereignishandlers einen Moment Zeit, um die Seite über einen Browser zu testen. Beachten Sie, wie jede Kategorie in einer Aufzählungsliste aufgeführt wird, in der der Name der Kategorie und die Anzahl der der Kategorie zugeordneten Produkte angezeigt werden (siehe Abbildung 4).
Abbildung 4: Name und Anzahl der Produkte jeder Kategorie werden angezeigt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Aktualisieren vonCategoriesDataTable
undCategoriesTableAdapter
, um die Anzahl der Produkte für jede Kategorie einzuschließen
Anstatt die Anzahl der Produkte für jede Kategorie zu bestimmen, da sie an den Repeater gebunden ist, können wir diesen Prozess optimieren, indem wir und CategoriesDataTable
CategoriesTableAdapter
in der Datenzugriffsebene so anpassen, dass diese Informationen nativ eingeschlossen werden. Um dies zu erreichen, müssen wir eine neue Spalte hinzufügen, um CategoriesDataTable
die Anzahl der zugeordneten Produkte zu enthalten. Um einer DataTable eine neue Spalte hinzuzufügen, öffnen Sie das Typisierte DataSet (App_Code\DAL\Northwind.xsd
), klicken Sie mit der rechten Maustaste auf die zu ändernde DataTable, und wählen Sie Hinzufügen/Spalte aus. Fügen Sie dem CategoriesDataTable
eine neue Spalte hinzu (siehe Abbildung 5).
Abbildung 5: Hinzufügen einer neuen Spalte zu (Klicken Sie hier, um dasCategoriesDataSource
Bild in voller Größe anzuzeigen)
Dadurch wird eine neue Spalte mit dem Namen Column1
hinzugefügt, die Sie ändern können, indem Sie einfach einen anderen Namen eingeben. Benennen Sie diese neue Spalte in um NumberOfProducts
. Als Nächstes müssen wir die Eigenschaften dieser Spalte konfigurieren. Klicken Sie auf die neue Spalte, und wechseln Sie zum Eigenschaftenfenster. Ändern Sie die Eigenschaft der DataType
Spalte von in System.String
, System.Int32
und legen Sie die ReadOnly
-Eigenschaft auf True
fest, wie in Abbildung 6 dargestellt.
Abbildung 6: Festlegen der DataType
Eigenschaften und ReadOnly
der neuen Spalte
Während der CategoriesDataTable
jetzt über eine NumberOfProducts
Spalte verfügt, wird sein Wert von keiner der entsprechenden TableAdapter-Abfragen festgelegt. Wir können die GetCategories()
-Methode aktualisieren, um diese Informationen zurückzugeben, wenn diese Informationen bei jedem Abruf von Kategorieinformationen zurückgegeben werden sollen. Wenn wir jedoch nur in seltenen Fällen (z. B. nur für dieses Tutorial) die Anzahl der zugeordneten Produkte für die Kategorien abrufen müssen, können wir unverändert bleiben GetCategories()
und eine neue Methode erstellen, die diese Informationen zurückgibt. Verwenden wir diesen letztgenannten Ansatz, um eine neue Methode namens zu GetCategoriesAndNumberOfProducts()
erstellen.
Um diese neue GetCategoriesAndNumberOfProducts()
Methode hinzuzufügen, klicken Sie mit der rechten Maustaste auf die CategoriesTableAdapter
, und wählen Sie Neue Abfrage aus. Dadurch wird der TableAdapter-Abfragekonfigurations-Assistent angezeigt, den wir in den vorherigen Tutorials mehrfach verwendet haben. Starten Sie für diese Methode den Assistenten, indem Sie angeben, dass die Abfrage eine Ad-hoc-SQL-Anweisung verwendet, die Zeilen zurückgibt.
Abbildung 7: Erstellen der Methode mithilfe einer Ad-hoc-SQL-Anweisung (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 8: Die SQL-Anweisung gibt Zeilen zurück (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Auf dem nächsten Assistentenbildschirm werden wir aufgefordert, die zu verwendende Abfrage einzugeben. Verwenden Sie die folgende SELECT
Anweisung, um die Felder der einzelnen Kategorien CategoryID
, CategoryName
und Description
zusammen mit der Anzahl der produkte zurückzugeben, die der Kategorie zugeordnet sind:
SELECT CategoryID, CategoryName, Description,
(SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
as NumberOfProducts
FROM Categories c
Abbildung 9: Angeben der zu verwendenden Abfrage (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Beachten Sie, dass die Unterabfrage, die die Anzahl der produkte berechnet, die der Kategorie zugeordnet sind, als NumberOfProducts
Alias verwendet wird. Diese Namensübereinstimmung bewirkt, dass der von dieser Unterabfrage zurückgegebene Wert der CategoriesDataTable
Spalte s NumberOfProducts
zugeordnet wird.
Nachdem Sie diese Abfrage eingegeben haben, müssen Sie im letzten Schritt den Namen für die neue Methode auswählen. Verwenden Sie FillWithNumberOfProducts
und GetCategoriesAndNumberOfProducts
für die Muster Eine DataTable ausfüllen bzw. Zurückgeben einer DataTable.
Abbildung 10: Benennen Sie die neuen TableAdapter-Methoden FillWithNumberOfProducts
und GetCategoriesAndNumberOfProducts
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
An diesem Punkt wurde die Datenzugriffsebene erweitert, um die Anzahl der Produkte pro Kategorie einzuschließen. Da alle Aufrufe an die DAL über eine separate Geschäftslogikebene weitergeleitet werden, müssen wir der CategoriesBLL
-Klasse eine entsprechende GetCategoriesAndNumberOfProducts
Methode hinzufügen:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable GetCategoriesAndNumberOfProducts()
{
return Adapter.GetCategoriesAndNumberOfProducts();
}
Wenn DAL und BLL abgeschlossen sind, sind wir bereit, diese Daten an den Categories
Repeater in CategoriesAndProducts.aspx
zu binden. Wenn Sie bereits eine ObjectDataSource für den Repeater aus dem Abschnitt Bestimmen der Anzahl von Produkten im ItemDataBound
Ereignishandler erstellt haben, löschen Sie diese ObjectDataSource, und entfernen Sie die Einstellung der Repeater-Eigenschaft DataSourceID
. Trennen Sie auch das Repeater s-Ereignis ItemDataBound
aus dem Ereignishandler, indem Sie die Handles Categories.OnItemDataBound
Syntax in der ASP.NET CodeBehind-Klasse entfernen.
Wenn sich der Repeater wieder im ursprünglichen Zustand befindet, fügen Sie über das Smarttag des Repeaters eine neue ObjectDataSource mit dem Namen CategoriesDataSource
hinzu. Konfigurieren Sie die ObjectDataSource so, dass die CategoriesBLL
-Klasse verwendet wird, aber anstatt die GetCategories()
-Methode zu verwenden, sollten Sie sie stattdessen verwenden GetCategoriesAndNumberOfProducts()
(siehe Abbildung 11).
Abbildung 11: Konfigurieren der ObjectDataSource für die Verwendung der GetCategoriesAndNumberOfProducts
-Methode (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Aktualisieren Sie als Nächstes, ItemTemplate
sodass die LinkButton-Eigenschaft deklarativ Text
mithilfe der Datenbindungssyntax zugewiesen wird und sowohl die CategoryName
Datenfelder als NumberOfProducts
auch enthält. Das vollständige deklarative Markup für den Repeater und die CategoriesDataSource
ObjectDataSource folgt:
<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:LinkButton runat="server" ID="ViewCategory"
Text='<%# String.Format("{0} ({1:N0})", _
Eval("CategoryName"), Eval("NumberOfProducts")) %>' />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategoriesAndNumberOfProducts" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
Die Ausgabe, die durch Aktualisieren der DAL gerendert wird, um eine NumberOfProducts
Spalte einzuschließen, entspricht der Verwendung des ItemDataBound
Ereignishandleransatzes (siehe Abbildung 4, um einen Screenshot des Repeaters mit den Kategorienamen und der Anzahl der Produkte anzuzeigen).
Schritt 3: Anzeigen der ausgewählten Produkte der Kategorie
An diesem Punkt haben wir den Categories
Repeater, der die Liste der Kategorien zusammen mit der Anzahl der Produkte in jeder Kategorie anzeigt. Der Repeater verwendet ein LinkButton-Element für jede Kategorie, die beim Klicken ein Postback verursacht. An diesem Punkt müssen wir diese Produkte für die ausgewählte Kategorie in der CategoryProducts
DataList anzeigen.
Eine Herausforderung besteht darin, wie die DataList nur die Produkte für die ausgewählte Kategorie anzeigt. Im Tutorial Master/Detail Using a Selectable Master GridView with a DetailsView (Details DetailsView ) wurde erläutert, wie Sie ein GridView-Objekt erstellen, dessen Zeilen ausgewählt werden können, wobei die Details der ausgewählten Zeilen in einer Detailansicht auf derselben Seite angezeigt werden. Die GridView s ObjectDataSource hat mithilfe der ProductsBLL
s-Methode GetProducts()
Informationen zu allen Produkten zurückgegeben, während die ObjectDataSource von DetailsView Mithilfe der GetProductsByProductID(productID)
-Methode Informationen zum ausgewählten Produkt abrufte. Der productID
Parameterwert wurde deklarativ bereitgestellt, indem er dem Wert der GridView-Eigenschaft SelectedValue
zugeordnet wurde. Leider verfügt der Repeater nicht über eine SelectedValue
-Eigenschaft und kann nicht als Parameterquelle dienen.
Hinweis
Dies ist eine dieser Herausforderungen, die bei der Verwendung von LinkButton in einem Repeater auftreten. Hätten wir stattdessen einen Link verwendet, um die CategoryID
abfragezeichenfolge zu übergeben, könnten wir dieses QueryString-Feld als Quelle für den Wert des Parameters verwenden.
Bevor wir uns jedoch Gedanken über das Fehlen einer SelectedValue
Eigenschaft für den Repeater machen, sollten wir zuerst die DataList an eine ObjectDataSource binden und deren ItemTemplate
angeben.
Wählen Sie im Smarttag DataList das Hinzufügen einer neuen ObjectDataSource mit dem Namen CategoryProductsDataSource
aus, und konfigurieren Sie sie für die Verwendung der s-Methode GetProductsByCategoryID(categoryID)
der ProductsBLL
Klasse. Da dataList in diesem Tutorial eine schreibgeschützte Schnittstelle bietet, können Sie die Dropdownlisten in den Registerkarten INSERT, UPDATE und DELETE auf (Keine) festlegen.
Abbildung 12: Konfigurieren der ObjectDataSource für die Verwendung ProductsBLL
der Klasse s-Methode (Klicken Sie hier, um ein Bild in voller Größe anzuzeigen)GetProductsByCategoryID(categoryID)
Da die GetProductsByCategoryID(categoryID)
-Methode einen Eingabeparameter (categoryID
) erwartet, können wir mit dem Assistenten Datenquelle konfigurieren die Quelle des Parameters angeben. Wenn die Kategorien in einem GridView- oder DataList-Objekt aufgeführt wurden, würden wir die Dropdownliste Parameterquelle auf Control und die ControlID auf die ID
des Datenwebsteuerelements festlegen. Da dem Repeater jedoch keine SelectedValue
Eigenschaft fehlt, kann er nicht als Parameterquelle verwendet werden. Wenn Sie dies überprüfen, stellen Sie fest, dass die Dropdownliste ControlID nur ein Steuerelement ID``CategoryProducts
enthält, das der ID
DataList.
Legen Sie vorerst die Dropdownliste Parameterquelle auf Keine fest. Wir weisen diesen Parameterwert programmgesteuert zu, wenn im Repeater auf eine Kategorie LinkButton geklickt wird.
Abbildung 13: Keine Parameterquelle für den categoryID
Parameter angeben (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten zum Konfigurieren von Datenquellen generiert Visual Studio automatisch die DataList-Datei ItemTemplate
. Ersetzen Sie diese Standardeinstellung ItemTemplate
durch die Vorlage, die wir im vorherigen Tutorial verwendet haben. Legen Sie außerdem die DataList-Eigenschaft RepeatColumns
auf 2 fest. Nachdem Sie diese Änderungen vorgenommen haben, sollte das deklarative Markup für Ihre DataList und die zugehörige ObjectDataSource wie folgt aussehen:
<asp:DataList ID="CategoryProducts" runat="server" DataKeyField="ProductID"
DataSourceID="CategoryProductsDataSource" RepeatColumns="2"
EnableViewState="False">
<ItemTemplate>
<h5><%# Eval("ProductName") %></h5>
<p>
Supplied by <%# Eval("SupplierName") %><br />
<%# Eval("UnitPrice", "{0:C}") %>
</p>
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="CategoryProductsDataSource"
OldValuesParameterFormatString="original_{0}" runat="server"
SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
<SelectParameters>
<asp:Parameter Name="categoryID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Derzeit ist der CategoryProductsDataSource
Parameter ObjectDataSource categoryID
nie festgelegt, sodass beim Anzeigen der Seite keine Produkte angezeigt werden. Wir müssen diesen Parameterwert basierend auf der CategoryID
der angeklickten Kategorie im Repeater festlegen. Dies führt zu zwei Herausforderungen: Erstens, wie bestimmen wir, wann auf ein LinkButton in den Repeater-Instanzen geklickt wurde, und zweitens ItemTemplate
, wie können wir die CategoryID
der entsprechenden Kategorie ermitteln, auf deren LinkButton geklickt wurde?
Das LinkButton-Steuerelement wie die Steuerelemente Button und ImageButton verfügt über ein Click
-Ereignis und ein Command
-Ereignis. Das Click
Ereignis ist so konzipiert, dass einfach darauf hingewiesen wird, dass auf linkButton geklickt wurde. Manchmal müssen wir jedoch nicht nur feststellen, dass auf linkButton geklickt wurde, auch einige zusätzliche Informationen an den Ereignishandler übergeben. Wenn dies der Fall ist, können die LinkButton-Eigenschaften CommandName
und CommandArgument
diese zusätzlichen Informationen zugewiesen werden. Wenn dann auf linkButton geklickt wird, wird das Command
-Ereignis (anstelle des Click
-Ereignisses) ausgelöst, und dem Ereignishandler werden die Werte der CommandName
Eigenschaften und CommandArgument
übergeben.
Wenn ein Command
Ereignis innerhalb einer Vorlage im Repeater ausgelöst wird, wird das Repeater-EreignisItemCommand
ausgelöst und die CommandName
Werte und CommandArgument
des geklickten LinkButton (oder Button oder ImageButton) übergeben. Um zu ermitteln, wann auf eine Kategorie LinkButton im Repeater geklickt wurde, müssen wir daher wie folgt vorgehen:
- Legen Sie die
CommandName
Eigenschaft von LinkButton in den Repeater aufItemTemplate
einen Wert fest (Ich habe ListProducts verwendet). Wenn Sie diesenCommandName
Wert festlegen, wird das LinkButton-EreignisCommand
ausgelöst, wenn auf linkButton geklickt wird. - Legen Sie die LinkButton-Eigenschaft
CommandArgument
auf den Wert des aktuellen Elements sCategoryID
fest. - Erstellen Sie einen Ereignishandler für das Repeater s-Ereignis
ItemCommand
. Legen Sie im Ereignishandler denCategoryProductsDataSource
ObjectDataSource-Parameter aufCategoryID
den Wert des übergebenenCommandArgument
fest.
Das folgende ItemTemplate
Markup für den Categories Repeater implementiert die Schritte 1 und 2. Beachten Sie, wie dem CommandArgument
Wert das Datenelement s CategoryID
mithilfe der Datenbindungssyntax zugewiesen wird:
<ItemTemplate>
<li>
<asp:LinkButton CommandName="ListProducts" runat="server"
CommandArgument='<%# Eval("CategoryID") %>' ID="ViewCategory"
Text='<%# string.Format("{0} ({1:N0})", _
Eval("CategoryName"), Eval("NumberOfProducts")) %>'>
</asp:LinkButton>
</li>
</ItemTemplate>
Beim Erstellen eines ItemCommand
Ereignishandlers ist es ratsam, immer zuerst den eingehenden CommandName
Wert zu überprüfen, da jedes Ereignis, dasCommand
von einem Button-, LinkButton- oder ImageButton-Element innerhalb des Repeaters ausgelöst wird, das ItemCommand
Ereignis auslöst. Obwohl derzeit nur ein LinkButton vorhanden ist, können wir (oder ein anderer Entwickler in unserem Team) dem Repeater zusätzliche Schaltflächen-Websteuerelemente hinzufügen, die beim Klicken auf denselben ItemCommand
Ereignishandler ausgelöst werden. Daher ist es am besten, immer sicherzustellen, dass Sie die CommandName
Eigenschaft überprüfen und nur dann mit Ihrer programmgesteuerten Logik fortfahren, wenn sie dem erwarteten Wert entspricht.
Nachdem sichergestellt wurde, dass der übergebene CommandName
Wert gleich ListProducts ist, weist der Ereignishandler den CategoryProductsDataSource
ObjectDataSource-Parameter CategoryID
dem Wert des übergebenen CommandArgument
zu. Diese Änderung an den ObjectDataSources SelectParameters
bewirkt automatisch, dass sich die DataList erneut an die Datenquelle bindet und die Produkte für die neu ausgewählte Kategorie anzeigt.
protected void Categories_ItemCommand(object source, RepeaterCommandEventArgs e)
{
// If it's the "ListProducts" command that has been issued...
if (string.Compare(e.CommandName, "ListProducts", true) == 0)
{
// Set the CategoryProductsDataSource ObjectDataSource's CategoryID parameter
// to the CategoryID of the category that was just clicked (e.CommandArgument)...
CategoryProductsDataSource.SelectParameters["CategoryID"].DefaultValue =
e.CommandArgument.ToString();
}
}
Mit diesen Ergänzungen ist unser Tutorial abgeschlossen! Nehmen Sie sich einen Moment Zeit, um es in einem Browser zu testen. Abbildung 14 zeigt den Bildschirm beim ersten Besuch der Seite. Da eine Kategorie noch ausgewählt wurde, werden keine Produkte angezeigt. Wenn Sie auf eine Kategorie wie "Produzieren" klicken, werden diese Produkte in der Kategorie Produkt in einer zweispaltigen Ansicht angezeigt (siehe Abbildung 15).
Abbildung 14: Beim ersten Besuch der Seite werden keine Produkte angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 15: Klicken auf die Kategorie "Produzieren" Listen übereinstimmende Produkte rechts (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Zusammenfassung
Wie in diesem Tutorial und im vorherigen Tutorial gezeigt, können master-/Detailberichte auf zwei Seiten verteilt oder auf einer seite konsolidiert werden. Das Anzeigen eines master-/Detailberichts auf einer einzelnen Seite stellt jedoch einige Herausforderungen hinsichtlich des optimalen Layouts der master- und Detaildatensätze auf der Seite dar. Im Tutorial Master/Detail Using a Selectable Master GridView with a Details DetailsView (Master/Detail Using a Selectable Master GridView with a Details DetailsView) wurden die Detaildatensätze über den master Datensätzen angezeigt. In diesem Tutorial haben wir CSS-Techniken verwendet, damit die master Datensätze links neben den Details angezeigt werden.
Neben der Anzeige von master/Detailberichten hatten wir auch die Möglichkeit, zu erkunden, wie die Anzahl der produkte abgerufen werden kann, die jeder Kategorie zugeordnet sind, und wie serverseitige Logik ausgeführt wird, wenn von einem Repeater aus auf einen LinkButton (oder Button oder ImageButton) geklickt wird.
In diesem Tutorial wird die Untersuchung von master/Detailberichten mit dataList und Repeater abgeschlossen. In unseren nächsten Tutorials wird veranschaulicht, wie Sie dem DataList-Steuerelement Bearbeitungs- und Löschfunktionen hinzufügen.
Viel Spaß beim Programmieren!
Weitere Informationen
Weitere Informationen zu den in diesem Tutorial erläuterten Themen finden Sie in den folgenden Ressourcen:
- Floatutorial ein Tutorial zu schwebenden CSS-Elementen mit CSS
- CSS-Positionierung weitere Informationen zum Positionieren von Elementen mit CSS
- Auslegen von Inhalten mit HTML mithilfe von
<table>
s und anderen HTML-Elementen für die Positionierung
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 Stunden. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.
Besonderen Dank an
Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Leitender Prüfer für dieses Tutorial war Zack Jones. Möchten Sie meine anstehenden 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