Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
von Scott Mitchell
In diesem Lernprogramm komprimieren wir den zweiseitigen Master/Detailbericht des vorherigen Lernprogramms in eine einzelne Seite, in der eine Aufzählung der Kategorienamen auf der linken Seite des Bildschirms und die Produkte der ausgewählten Kategorie rechts auf dem Bildschirm angezeigt werden.
Einführung
Im vorherigen Lernprogramm haben wir uns angesehen, wie ein Master-/Detailbericht auf zwei Seiten getrennt wird. Auf der Gestaltungsvorlage haben wir ein Repeater-Steuerelement zum Rendern einer Aufzählung von Kategorien verwendet. Jeder Kategoriename war ein Link, der den Benutzer beim Klicken auf die Detailseite bringen würde, auf der eine zweispaltige DataList diese Produkte anzeigte, die zur ausgewählten Kategorie gehören.
In diesem Lernprogramm komprimieren wir das Lernprogramm auf zwei Seiten in eine einzelne Seite, in der eine Aufzählung von 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 erzeugt und die Produkte der ausgewählten Kategorie an eine zweispaltige DataList auf der rechten Seite des Bildschirms gebunden. Neben der Anzeige jedes Kategorienamens zeigt der Repeater auf der linken Seite, wie viele Produkte 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 Bild in voller Größe anzuzeigen)
Schritt 1: Anzeigen eines Repeaters im linken Bereich des Bildschirms
Für dieses Lernprogramm müssen die Aufzählung der Kategorien links neben den produkten der ausgewählten Kategorie angezeigt werden. Inhalte innerhalb einer Webseite können mithilfe von Standard-HTML-Element-Absatztags, nicht unterbrechenden Leerzeichen, <table>
S usw. mithilfe von CSS-Techniken (Cascading Stylesheet) positioniert werden. Alle unsere Lernprogramme haben bisher CSS-Techniken für die Positionierung verwendet. Wenn wir die Navigations-Benutzeroberfläche in unserer Gestaltungsvorlage im Lernprogramm "Gestaltungsvorlagen" und "Websitenavigation" erstellt haben, haben wir absolute Positionierung verwendet, die den genauen Pixeloffset für die Navigationsliste und den Hauptinhalt angibt. Alternativ kann CSS verwendet werden, um ein Element rechts oder links von einer anderen über unverankert zu positionieren. Die Aufzählung der Kategorien kann links neben den Produkten der ausgewählten Kategorie angezeigt werden, indem der Repeater links neben der DataList schwebt.
Öffnen Sie die CategoriesAndProducts.aspx
Seite aus dem DataListRepeaterFiltering
Ordner, und fügen Sie der Seite einen Repeater und eine DataList hinzu. Legen Sie die Repeater ID
auf Categories
und die DataList s auf CategoryProducts
. Wechseln Sie zur Quellansicht, und platzieren Sie die Steuerelemente "Repeater" und "DataList" in ihren eigenen <div>
Elementen. Das heißt, schließen Sie den Repeater zuerst in ein <div>
Element ein, und geben Sie dann die DataList direkt hinter dem Repeater in ein eigenes <div>
Element ein. Ihr Markup sollte an diesem Punkt ähnlich 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>
Das float: left;
erste <div>
Element wird links neben dem zweiten Element schwebt. Die width
Einstellungen padding-right
geben die ersten <div>
und width
den Abstand zwischen dem Inhalt des <div>
Elements und dem rechten Rand an. Weitere Informationen zu unverankerten Elementen in CSS finden Sie im Floatutorial.For more information on floating elements in CSS check out the Floatutorial.
Anstatt die Formatvorlageneinstellung direkt über das Attribut des ersten <p>
Elements style
anzugeben, erstellen wir stattdessen eine neue CSS-Klasse mit Styles.css
dem Namen FloatLeft
:
.FloatLeft
{
float: left;
width: 33%;
padding-right: 10px;
}
Dann können wir das <div>
durch <div class="FloatLeft">
.
Nachdem Sie die CSS-Klasse hinzugefügt und das Markup auf der CategoriesAndProducts.aspx
Seite konfiguriert haben, wechseln Sie zum Designer. Sie sollten sehen, dass der Repeater links neben der DataList schwebt (obwohl beide jetzt nur als graue Felder angezeigt werden, da wir ihre Datenquellen oder Vorlagen noch konfiguriert haben).
Abbildung 2: Der Repeater wird links neben 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 zu jedem Kategorienamen auch die Anzahl der Produkte anzeigen, die der Kategorie zugeordnet sind. Um auf diese Informationen zuzugreifen, können wir eine der folgenden Aktionen ausführen:
- Ermitteln Sie diese Informationen aus der codeBehind-Klasse der ASP.NET Seite. Aufgrund eines bestimmten Vorgangs
categoryID
können wir die Anzahl der zugeordneten Produkte ermitteln, indem dieProductsBLL
Klasse s-MethodeGetProductsByCategoryID(categoryID)
aufgerufen wird. Diese Methode gibt einProductsDataTable
Objekt zurück, dessenCount
Eigenschaft angibt, wie vieleProductsRow
Elemente vorhanden sind. Dies ist die Anzahl der Produkte für das angegebene ObjektcategoryID
. Wir können einenItemDataBound
Ereignishandler für den Repeater erstellen, der für jede Kategorie, die an den Repeater gebunden ist, die Methode derProductsBLL
KlasseGetProductsByCategoryID(categoryID)
aufruft und deren Anzahl in die Ausgabe einschließt. - Aktualisieren Sie das
CategoriesDataTable
in "Typed DataSet" enthaltene Datensatz, um eineNumberOfProducts
Spalte einzuschließen. Anschließend können wir dieGetCategories()
MethodeCategoriesDataTable
aktualisieren, um diese Informationen einzuschließen oder alternativ die belassene Methode wie folgt zu belassenGetCategories()
und eine neueCategoriesDataTable
Methode zu erstellen, die aufgerufen wirdGetCategoriesAndNumberOfProducts()
.
Lassen Sie uns beide Techniken untersuchen. Der erste Ansatz ist einfacher zu implementieren, da wir die Datenzugriffsschicht nicht aktualisieren müssen. Dies erfordert jedoch mehr Kommunikation mit der Datenbank. Der Aufruf der ProductsBLL
Klassenmethode GetProductsByCategoryID(categoryID)
im ItemDataBound
Ereignishandler fügt einen zusätzlichen Datenbankaufruf für jede Kategorie hinzu, die im Repeater angezeigt wird. Bei dieser Technik gibt es N +1-Datenbankaufrufe, wobei N die Anzahl der Kategorien ist, die im Repeater angezeigt werden. Mit dem zweiten Ansatz wird die Produktanzahl mit Informationen zu jeder Kategorie aus der CategoriesBLL
Klasse GetCategories()
(oder GetCategoriesAndNumberOfProducts()
) Methode zurückgegeben, wodurch nur eine Reise in die Datenbank entsteht.
Ermitteln der Anzahl der Produkte im ItemDataBound-Ereignishandler
Die Bestimmung der Anzahl der Produkte 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 hinzu, die über das Smarttag "Repeater" benannt CategoriesDataSource
ist. Konfigurieren Sie als Nächstes die CategoriesDataSource
ObjectDataSource so, dass sie ihre Daten aus der CategoriesBLL
Klassenmethode GetCategories()
abruft.
Abbildung 3: Konfigurieren der ObjectDataSource für die Verwendung der Methode der CategoriesBLL
Klasse GetCategories()
(Klicken, um das Bild in voller Größe anzuzeigen)
Jedes Element im Categories
Repeater muss klickbar sein und bewirkt, dass die CategoryProducts
DataList diese Produkte für die ausgewählte Kategorie anzeigt. Dies kann erreicht werden, indem jede Kategorie zu einem Link erstellt wird, der wieder mit derselben Seite (CategoriesAndProducts.aspx
) verknüpft wird, aber die Durchlauf der CategoryID
Abfragezeichenfolge, ähnlich wie im vorherigen Lernprogramm. Der Vorteil dieses Ansatzes besteht darin, dass eine Seite, die produkte einer bestimmten Kategorie anzeigt, von einer Suchmaschine mit Lesezeichen versehen und indiziert werden kann.
Alternativ können wir jede Kategorie als LinkButton festlegen. Dies ist der Ansatz, den wir für dieses Lernprogramm verwenden werden. Das LinkButton-Element wird im Browser des Benutzers als Link gerendert, führt aber bei Klick zu einem Postback; bei postback muss die DataList s ObjectDataSource aktualisiert werden, um diese Produkte anzuzeigen, die zur ausgewählten Kategorie gehören. Für dieses Lernprogramm ist die Verwendung eines Links sinnvoller als die Verwendung eines LinkButton; Es kann jedoch auch andere Szenarien geben, in denen die Verwendung eines LinkButton-Elements vorteilhafter ist. Der Linkansatz wäre zwar ideal für dieses Beispiel, lassen Sie uns stattdessen die Verwendung von LinkButton erkunden. Wie wir sehen, führt die Verwendung eines LinkButton-Steuerelements einige Herausforderungen ein, die sonst nicht mit einem Link auftreten würden. Daher werden durch die Verwendung eines LinkButton-Elements in diesem Lernprogramm diese Herausforderungen hervorgehoben und Lösungen für diese Szenarien bereitgestellt, in denen wir möglicherweise ein LinkButton anstelle eines Links verwenden möchten.
Hinweis
Sie werden ermutigt, dieses Lernprogramm mithilfe eines HyperLink-Steuerelements oder <a>
-Elements 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 Lernprogramm muss der Repeater seinen Ansichtszustand aktiviert haben (beachten Sie das Auslassen der EnableViewState="False"
deklarativen Syntax des Repeaters). In Schritt 3 erstellen wir einen Ereignishandler für das Repeater-Ereignis ItemCommand
, in dem die ObjectDataSource-Auflistung SelectParameters
von DataList aktualisiert wird. Die Repeater werden jedoch nicht ausgelöst, wenn der Ansichtszustand ItemCommand
deaktiviert ist.
Das LinkButton-Objekt mit dem Eigenschaftswert von besitzt keinen Eigenschaftensatz.The LinkButton with the ID
property value of ViewCategory
does not have its Text
property set. Wenn wir nur den Kategorienamen anzeigen wollten, hätten wir die Text-Eigenschaft deklarativ über die Datenbindungssyntax festgelegt, z. B.:
<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 einen Aufruf der Methode der ProductBLL
Klasse GetCategoriesByProductID(categoryID)
ausführen und bestimmen, wie viele Datensätze im Ergebnis 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);
}
}
Wir beginnen mit der Sicherstellung, dass wir mit einem Datenelement arbeiten (eines, dessen ItemType
Ist oder Item
) ist AlternatingItem
und dann auf die CategoriesRow
Instanz verweist, die gerade an den aktuellen RepeaterItem
gebunden wurde. Als Nächstes bestimmen wir die Anzahl der Produkte für diese Kategorie, indem eine Instanz der ProductsBLL
Klasse erstellt, die GetCategoriesByProductID(categoryID)
Methode aufgerufen und die Anzahl der mit der Count
Eigenschaft zurückgegebenen Datensätze bestimmt wird. Schließlich ist das ViewCategory
LinkButton-Element in der ItemTemplate Verweise, und seine Text
Eigenschaft wird auf CategoryName (NumberOfProductsInCategory) festgelegt, wobei NumberOfProductsInCategory als Zahl mit null Dezimalstellen formatiert ist.
Hinweis
Alternativ könnten wir der codeBehind-Klasse der ASP.NET Seite eine Formatierungsfunktion hinzugefügt haben, die eine Kategorie CategoryName
und CategoryID
Werte akzeptiert und die CategoryName
verkettete Anzahl von Produkten in der Kategorie zurückgibt (wie durch Aufrufen der GetCategoriesByProductID(categoryID)
Methode bestimmt). Die Ergebnisse einer solchen Formatierungsfunktion können deklarativ der LinkButton-Text-Eigenschaft zugewiesen werden, die die Notwendigkeit des ItemDataBound
Ereignishandlers ersetzt. Weitere Informationen zur Verwendung von Formatierungsfunktionen finden Sie in den Lernprogrammen "Using TemplateFields" im GridView-Steuerelement oder "Formatieren von DataList" und "Repeater Based Upon Data ".
Nachdem Sie diesen Ereignishandler hinzugefügt haben, nehmen Sie sich einen Moment Zeit, um die Seite über einen Browser zu testen. Beachten Sie, wie jede Kategorie in einer Aufzählung aufgeführt wird, wobei der Name der Kategorie und die Anzahl der Produkte angezeigt werden, die der Kategorie zugeordnet sind (siehe Abbildung 4).
Abbildung 4: Jeder Kategoriename und die Anzahl der Produkte werden angezeigt (Zum Anzeigen des Bilds mit voller Größe klicken)
Aktualisieren derCategoriesDataTable
UndCategoriesTableAdapter
einschließen der Anzahl der Produkte für jede Kategorie
Anstatt die Anzahl der Produkte für jede Kategorie zu ermitteln, die an den Repeater gebunden ist, können wir diesen Prozess optimieren, indem wir die CategoriesDataTable
Datenzugriffsebene anpassen, CategoriesTableAdapter
um diese Informationen nativ einzuschließen. Um dies zu erreichen, müssen wir eine neue Spalte hinzufügen, um CategoriesDataTable
die Anzahl der zugehörigen Produkte zu enthalten. Um einer DataTable eine neue Spalte hinzuzufügen, öffnen Sie das typierte 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 der CategoriesDataTable
Spalte eine neue Spalte hinzu (siehe Abbildung 5).
Abbildung 5: Hinzufügen einer neuen Spalte zum CategoriesDataSource
Bild in voller Größe (Klicken, um das Bild in voller Größe anzuzeigen)
Dadurch wird eine neue Spalte namens Column1
hinzugefügt, die Sie ändern können, indem Sie einfach einen anderen Namen eingeben. Benennen Sie diese neue Spalte in 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 Spalte DataType
in System.String
System.Int32
die Eigenschaft, und legen Sie sie ReadOnly
wie in Abbildung 6 dargestellt auf True
fest.
Abbildung 6: Festlegen der DataType
Eigenschaften ReadOnly
der neuen Spalte
Obwohl die CategoriesDataTable
Spalte jetzt über eine NumberOfProducts
Spalte verfügt, wird der Wert von keiner der entsprechenden TableAdapter-Abfragen festgelegt. Wir können die GetCategories()
Methode aktualisieren, um diese Informationen zurückzugeben, wenn diese Informationen jedes Mal zurückgegeben werden sollen, wenn Kategorieinformationen abgerufen werden. Wenn wir jedoch nur die Anzahl der zugehörigen Produkte für die Kategorien in seltenen Fällen abrufen müssen (z. B. nur für dieses Lernprogramm), können wir dies belassen GetCategories()
und eine neue Methode erstellen, die diese Informationen zurückgibt. Lassen Sie uns diesen letzteren Ansatz verwenden, indem wir eine neue Methode mit dem Namen GetCategoriesAndNumberOfProducts()
erstellen.
Um diese neue GetCategoriesAndNumberOfProducts()
Methode hinzuzufügen, klicken Sie mit der rechten Maustaste auf die CategoriesTableAdapter
neue Abfrage, und wählen Sie "Neue Abfrage" aus. Dadurch wird der TableAdapter-Abfragekonfigurations-Assistent angezeigt, den wir in früheren Lernprogrammen 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, um das Bild in voller Größe anzuzeigen)
Abbildung 8: Die SQL-Anweisung gibt Zeilen zurück (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Auf dem nächsten Assistentenbildschirm werden wir aufgefordert, die zu verwendende Abfrage zu verwenden. Verwenden Sie die folgende CategoryID
Anweisung, um die einzelnen Kategorien CategoryName
Description
und SELECT
Felder 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 (Zum Anzeigen des Bilds mit voller Größe klicken)
Beachten Sie, dass die Unterabfrage, die die Anzahl der Produkte berechnet, die der Kategorie zugeordnet sind, als Alias verwendet NumberOfProducts
wird. Diese Namensüberstimmung bewirkt, dass der von dieser Unterabfrage zurückgegebene Wert der CategoriesDataTable
Spalte "s NumberOfProducts
" zugeordnet wird.
Nach der Eingabe dieser Abfrage besteht der letzte Schritt darin, den Namen für die neue Methode auszuwählen. Verwenden Sie FillWithNumberOfProducts
bzw GetCategoriesAndNumberOfProducts
. für die Füllung einer DataTable und zurückgeben Sie ein DataTable-Muster.
Abbildung 10: Benennen der Methoden FillWithNumberOfProducts
des neuen TableAdapter-Elements und GetCategoriesAndNumberOfProducts
(Klicken Sie, 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 der Präsentationsebene über eine separate Geschäftslogikebene an die DAL weitergeleitet werden, müssen wir der GetCategoriesAndNumberOfProducts
Klasse eine entsprechende CategoriesBLL
Methode hinzufügen:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable GetCategoriesAndNumberOfProducts()
{
return Adapter.GetCategoriesAndNumberOfProducts();
}
Nachdem dal und BLL abgeschlossen sind, sind wir bereit, diese Daten an den Categories
Repeater zu binden!CategoriesAndProducts.aspx
Wenn Sie bereits eine ObjectDataSource für den Repeater aus dem Abschnitt "Bestimmen der Anzahl der Produkte" im ItemDataBound
Abschnitt "Ereignishandler" erstellt haben, löschen Sie diese ObjectDataSource, und entfernen Sie die Eigenschaftseinstellung des DataSourceID
Repeaters. Entfernen Sie auch das Repeater-Ereignis ItemDataBound
aus dem Ereignishandler, indem Sie die Handles Categories.OnItemDataBound
Syntax in der ASP.NET CodeBehind-Klasse entfernen.
Fügen Sie mit dem Repeater im ursprünglichen Zustand eine neue ObjectDataSource hinzu, die über das Smarttag "Repeater" benannt CategoriesDataSource
ist. Konfigurieren Sie objectDataSource so, dass sie die CategoriesBLL
Klasse verwendet, aber statt sie verwenden zu GetCategories()
lassen, verwenden Sie sie GetCategoriesAndNumberOfProducts()
stattdessen (siehe Abbildung 11).
Abbildung 11: Konfigurieren der ObjectDataSource für die Verwendung der GetCategoriesAndNumberOfProducts
Methode (Klicken, um das Bild in voller Größe anzuzeigen)
Aktualisieren Sie als Nächstes, ItemTemplate
dass die LinkButton-Eigenschaft Text
deklarativ mithilfe der Datenbindungssyntax zugewiesen wird und sowohl die Felder als CategoryName
auch die NumberOfProducts
Datenfelder enthält. Das vollständige deklarative Markup für den Repeater und die CategoriesDataSource
ObjectDataSource folgen:
<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 Produkte der ausgewählten Kategorie
An diesem Punkt zeigt der Categories
Repeater die Liste der Kategorien zusammen mit der Anzahl der Produkte in jeder Kategorie an. Der Repeater verwendet ein LinkButton für jede Kategorie, die, wenn sie geklickt wird, zu einem Postback führt, an dem wir diese Produkte für die ausgewählte Kategorie in der DataList anzeigen müssen.The Repeater uses a LinkButton for each category that when clicked, when clicked, a postback, at which point we need to display those products for the selected category in the CategoryProducts
DataList.
Eine Herausforderung, die uns gegenübersteht, besteht darin, dass die DataList nur diese Produkte für die ausgewählte Kategorie anzeigt.
Im Master/Detail Using a Selectable Master GridView with a Details DetailsView tutorial we saw how to build a GridView whose rows could be selected, with the selected row s details being displayed in a DetailsView on the same page. Die GridView s ObjectDataSource hat Informationen zu allen Produkten mit der ProductsBLL
s-Methode GetProducts()
zurückgegeben, während die DetailsView s ObjectDataSource Informationen über das ausgewählte Produkt mithilfe der GetProductsByProductID(productID)
Methode abgerufen hat. 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 der Herausforderungen, die beim Verwenden von LinkButton in einem Repeater auftreten. Wenn wir stattdessen einen Hyperlink zum Übergeben der CategoryID
Abfragezeichenfolge verwendet haben, konnten wir dieses QueryString-Feld als Quelle für den Wert des Parameters verwenden.
Bevor wir uns jedoch gedanken über den Mangel an SelectedValue
Eigenschaft für den Repeater machen, lassen Sie uns zuerst die DataList an eine ObjectDataSource binden und deren ItemTemplate
Eigenschaft angeben.
Wählen Sie im Smarttag von DataList ein neues ObjectDataSource-Element hinzu CategoryProductsDataSource
, und konfigurieren Sie sie für die Verwendung der ProductsBLL
Klassenmethode GetProductsByCategoryID(categoryID)
. Da die DataList in diesem Lernprogramm 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 Klassenmethode GetProductsByCategoryID(categoryID)
(Klicken, um das Bild in voller Größe anzuzeigen)
Da die GetProductsByCategoryID(categoryID)
Methode einen Eingabeparameter erwartet (categoryID
), ermöglicht uns der Assistent "Datenquelle konfigurieren" die Angabe der Quelle des Parameters. Wenn die Kategorien in einer GridView oder einer DataList aufgeführt wurden, haben wir die Dropdownliste "Parameterquelle" auf "Control" und "ControlID" auf das ID
Datenwebsteuerelement festgelegt. Da der Repeater jedoch keine SelectedValue
Eigenschaft aufweist, kann er nicht als Parameterquelle verwendet werden. Wenn Sie überprüfen, werden Sie feststellen, dass die Dropdownliste "ControlID" nur ein Steuerelement ID``CategoryProducts
enthält, das ID
der DataList entspricht.
Legen Sie vorerst die Dropdownliste "Parameterquelle" auf "Keine" fest. Dieser Parameterwert wird programmgesteuert zugewiesen, wenn im Repeater auf ein LinkButton-Element der Kategorie geklickt wird.
Abbildung 13: Angeben einer Parameterquelle für den categoryID
Parameter (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten zum Konfigurieren von Datenquellen generiert Visual Studio die DataList s ItemTemplate
automatisch. Ersetzen Sie diese Standardeinstellung ItemTemplate
durch die Vorlage, die wir im vorherigen Lernprogramm verwendet haben. Legen Sie außerdem die DataList s-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 wird der CategoryProductsDataSource
Parameter ObjectDataSource categoryID
nie festgelegt, sodass beim Anzeigen der Seite keine Produkte angezeigt werden. Was wir tun müssen, ist, dass dieser Parameterwert basierend auf der CategoryID
angeklickten Kategorie im Repeater festgelegt ist. Dies führt zu zwei Herausforderungen: Wie bestimmen wir zunächst, wann auf ein LinkButton-Element in den Repeater-Steuerelementen ItemTemplate
geklickt wurde, und zweitens, wie können wir die CategoryID
entsprechende Kategorie bestimmen, auf deren LinkButton geklickt wurde?
Das LinkButton-Steuerelement wie die Button- und ImageButton-Steuerelemente verfügt über ein Click
Ereignis und ein Command
Ereignis. Das Click
Ereignis wurde entwickelt, um einfach zu beachten, dass auf das LinkButton-Element geklickt wurde. Manchmal müssen wir jedoch nicht nur darauf hinweisen, dass auf das LinkButton-Element geklickt wurde, wir müssen auch einige zusätzliche Informationen an den Ereignishandler übergeben. Wenn dies der Fall ist, können die LinkButton-Objekte CommandName
und CommandArgument
-Eigenschaften diesen zusätzlichen Informationen zugewiesen werden. Wenn dann auf das LinkButton-Objekt geklickt wird, wird das Command
Ereignis (anstelle des Click
Ereignisses) ausgelöst, und der Ereignishandler wird die Werte der CommandName
Und CommandArgument
Eigenschaften übergeben.
Wenn ein Command
Ereignis aus einer Vorlage im Repeater ausgelöst wird, wird das Repeater-Ereignis ItemCommand
ausgelöst und die CommandName
Werte CommandArgument
des angeklickten LinkButton (oder Button oder ImageButton) übergeben. Um zu ermitteln, wann auf ein Kategorie-LinkButton-Element im Repeater geklickt wurde, müssen wir folgende Schritte ausführen:
- Legen Sie die
CommandName
Eigenschaft von LinkButton in den Repeater-SteuerelementenItemTemplate
auf einen bestimmten Wert fest (ich habe ListProducts verwendet). Durch Festlegen diesesCommandName
Werts wird das LinkButton-EreignisCommand
ausgelöst, wenn auf das LinkButton-Element geklickt wird. - Legen Sie die LinkButton s-Eigenschaft
CommandArgument
auf den Wert der aktuellen Elemente festCategoryID
. - Erstellen Sie einen Ereignishandler für das Repeater-Ereignis
ItemCommand
. Legen Sie im Ereignishandler denCategoryProductsDataSource
Parameter ObjectDataSource aufCategoryID
den Wert des übergebenenCommandArgument
Objekts fest.
Das folgende ItemTemplate
Markup für den Categories Repeater implementiert die Schritte 1 und 2. Beachten Sie, wie dem CommandArgument
Wert die Datenelements CategoryID
mithilfe der Datenbindungssyntax zugewiesen werden:
<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>
Jedes Mal, wenn ein ItemCommand
Ereignishandler erstellt wird, ist es umsichtig, immer zuerst den eingehenden CommandName
Wert zu überprüfen, da jedesCommand
Ereignis, das von einem Button -, LinkButton- oder ImageButton-Element innerhalb des Repeaters ausgelöst wird, das ItemCommand
Ereignis ausgelöst wird. Obwohl wir derzeit nur über ein solches LinkButton verfügen, könnten 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 mit Ihrer programmgesteuerten Logik fortfahren, wenn sie mit dem erwarteten Wert übereinstimmt.
Nachdem sichergestellt wurde, dass der übergebene CommandName
Wert ListProducts entspricht, weist der Ereignishandler dann dem Wert des übergebenen CategoryProductsDataSource
Objekts den CategoryID
Parameter ObjectDataSource CommandArgument
zu. Durch diese Änderung an den ObjectDataSource-Objekten SelectParameters
wird die DataList automatisch mit der Datenquelle verknüpft, wobei die Produkte für die neu ausgewählte Kategorie angezeigt werden.
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 Lernprogramm 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 noch keine Kategorie ausgewählt werden muss, werden keine Produkte angezeigt. Wenn Sie auf eine Kategorie klicken, z. B. "Produzieren", 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 (Zum Anzeigen des Bilds mit voller Größe klicken)
Abbildung 15: Klicken auf die Kategorie "Produzieren" listet die übereinstimmenden Produkte rechts auf (Klicken, um das Bild in voller Größe anzuzeigen)
Zusammenfassung
Wie wir in diesem Lernprogramm und dem vorherigen gesehen haben, können Master-/Detailberichte auf zwei Seiten verteilt oder auf einer Seite konsolidiert werden. Das Anzeigen eines Master-/Detailberichts auf einer einzelnen Seite führt jedoch einige Herausforderungen zum Layout des Master- und Detaildatenblatts auf der Seite ein. Im Master/Detail Using a Selectable Master GridView with a Details DetailsView tutorial we had the details records appear above the master records; in this tutorial we used CSS techniques to have the master records float to the left of the details.
Zusammen mit der Anzeige von Master-/Detailberichten hatten wir auch die Möglichkeit, die Anzahl der produkte abzurufen, die jeder Kategorie zugeordnet sind, sowie wie serverseitige Logik ausgeführt wird, wenn ein LinkButton (oder Button oder ImageButton) in einem Repeater klickt.
Dieses Lernprogramm schließt unsere Untersuchung von Master-/Detailberichten mit der DataList und dem Repeater ab. In unseren nächsten Lernprogrammen wird veranschaulicht, wie Sie dem DataList-Steuerelement Bearbeitungs- und Löschfunktionen hinzufügen.
Glückliche Programmierung!
Weitere nützliche Informationen
Weitere Informationen zu den in diesem Lernprogramm erläuterten Themen finden Sie in den folgenden Ressourcen:
- Floatutorial ein Tutorial über das Schweben von CSS-Elementen mit CSS
- CSS-Positionierung weitere Informationen zur Positionierung von Elementen mit CSS
-
Gestalten von Inhalten mit HTML mithilfe von
<table>
s und anderen HTML-Elementen zur Positionierung
Zum Autor
Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.
Besonderer Dank an
Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Lead Reviewer für dieses Lernprogramm war Zack Jones. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.