Hinzufügen einer GridView-Spalte mit Optionsfeldern (C#)
von Scott Mitchell
In diesem Tutorial erfahren Sie, wie Sie einem GridView-Steuerelement eine Spalte mit Optionsfeldern hinzufügen, um dem Benutzer eine intuitivere Möglichkeit zum Auswählen einer einzelnen Zeile des GridView-Steuerelements zu bieten.
Einführung
Das GridView-Steuerelement bietet viele integrierte Funktionen. Es enthält eine Reihe verschiedener Felder zum Anzeigen von Text, Bildern, Hyperlinks und Schaltflächen. Es unterstützt Vorlagen für weitere Anpassungen. Mit wenigen Mausklicks ist es möglich, eine GridView zu erstellen, in der jede Zeile über eine Schaltfläche ausgewählt werden kann, oder um Bearbeitungs- oder Löschfunktionen zu aktivieren. Trotz der Vielzahl der bereitgestellten Features gibt es häufig Situationen, in denen zusätzliche, nicht unterstützte Features hinzugefügt werden müssen. In diesem Und den nächsten beiden Lernprogramm wird untersucht, wie Sie die GridView-Funktionalität erweitern, um zusätzliche Features einzuschließen.
Dieses und das nächste Tutorial konzentrieren sich auf die Verbesserung des Zeilenauswahlprozesses. Wie in master/detail Using a Selectable Master GridView with a Details DetailView untersucht, können wir der GridView ein CommandField hinzufügen, das eine Schaltfläche Auswählen enthält. Wenn Sie darauf klicken, wird ein Postback ausgeführt, und die GridView-Eigenschaft SelectedIndex
wird auf den Index der Zeile aktualisiert, auf deren Schaltfläche Auswählen geklickt wurde. Im Tutorial Master/Detail Using a Selectable Master GridView with a Details DetailView (Master/Detail) Using a Selectable Master GridView with a Details DetailView (Master/Detail Using a Selectable Master GridView with a Details DetailView ) wurde erläutert, wie Sie dieses Feature verwenden, um Details für die ausgewählte GridView-Zeile anzuzeigen.
Obwohl die Schaltfläche Auswählen in vielen Situationen funktioniert, funktioniert sie möglicherweise nicht so gut für andere. Anstatt eine Schaltfläche zu verwenden, werden häufig zwei andere Benutzeroberflächenelemente für die Auswahl verwendet: das Optionsfeld und das Kontrollkästchen. Wir können gridView so erweitern, dass anstelle einer Schaltfläche Auswählen jede Zeile ein Optionsfeld oder ein Kontrollkästchen enthält. In Szenarien, in denen der Benutzer nur einen der GridView-Datensätze auswählen kann, wird das Optionsfeld möglicherweise der Schaltfläche Auswählen vorgezogen. In Situationen, in denen der Benutzer möglicherweise mehrere Datensätze auswählen kann, z. B. in einer webbasierten E-Mail-Anwendung, wo ein Benutzer möglicherweise mehrere Nachrichten zum Löschen auswählen möchte, bietet das Kontrollkästchen Funktionen, die nicht über die Schaltfläche Auswählen oder optionsfeld-Benutzeroberflächen verfügbar sind.
In diesem Tutorial erfahren Sie, wie Sie der GridView-Ansicht eine Spalte mit Optionsfeldern hinzufügen. Das weitere Tutorial untersucht die Verwendung von Kontrollkästchen.
Schritt 1: Erstellen der Erweiterung der GridView-Webseiten
Bevor wir mit der Erweiterung von GridView beginnen, um eine Spalte mit Optionsfeldern einzuschließen, nehmen wir uns zunächst einen Moment Zeit, um die ASP.NET Seiten in unserem Websiteprojekt zu erstellen, die wir für dieses Tutorial und die nächsten beiden benötigen. Fügen Sie zunächst einen neuen Ordner mit dem Namen hinzu EnhancedGridView
. Fügen Sie als Nächstes die folgenden ASP.NET Seiten zu diesem Ordner hinzu, und stellen Sie sicher, dass Sie jede Seite der Site.master
master Seite zuordnen:
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
Abbildung 1: Hinzufügen der ASP.NET-Seiten für die SqlDataSource-Related Tutorials
Wie in den anderen Ordnern Default.aspx
listet der EnhancedGridView
Ordner die Tutorials in seinem Abschnitt auf. Denken Sie daran, dass das SectionLevelTutorialListing.ascx
Benutzersteuerelement diese Funktionalität bereitstellt. Fügen Sie daher dieses Benutzersteuerelement zu Default.aspx
hinzu, indem Sie es vom Projektmappen-Explorer in die Entwurfsansicht der Seite ziehen.
Abbildung 2: Hinzufügen des SectionLevelTutorialListing.ascx
Benutzersteuerelements zu (Klicken Sie hier, umDefault.aspx
das Bild in voller Größe anzuzeigen)
Fügen Sie schließlich diese vier Seiten als Einträge zur Web.sitemap
Datei hinzu. Fügen Sie insbesondere das folgende Markup nach dem Verwenden des SqlDataSource-Steuerelements <siteMapNode>
hinzu:
<siteMapNode
title="Enhancing the GridView"
url="~/EnhancedGridView/Default.aspx"
description="Augment the user experience of the GridView control.">
<siteMapNode
url="~/EnhancedGridView/RadioButtonField.aspx"
title="Selection via a Radio Button Column"
description="Explore how to add a column of radio buttons in the GridView." />
<siteMapNode
url="~/EnhancedGridView/CheckBoxField.aspx"
title="Selection via a Checkbox Column"
description="Select multiple records in the GridView by using a column of
checkboxes." />
<siteMapNode
url="~/EnhancedGridView/InsertThroughFooter.aspx"
title="Add New Records through the Footer"
description="Learn how to allow users to add new records through the
GridView's footer." />
</siteMapNode>
Nehmen Sie sich nach dem Aktualisieren Web.sitemap
einen Moment Zeit, um die Tutorials-Website über einen Browser anzuzeigen. Das Menü auf der linken Seite enthält nun Elemente zum Bearbeiten, Einfügen und Löschen von Tutorials.
Abbildung 3: Die Websiteübersicht enthält jetzt Einträge für die Tutorials zur Verbesserung der GridView
Schritt 2: Anzeigen der Lieferanten in einer GridView
In diesem Tutorial wird ein GridView-Objekt erstellt, das die Lieferanten aus den USA auflistet, wobei jede GridView-Zeile ein Optionsfeld bereitstellt. Nach auswahl eines Lieferanten über das Optionsfeld kann der Benutzer die Produkte des Lieferanten anzeigen, indem er auf eine Schaltfläche klickt. Obwohl diese Aufgabe trivial klingen mag, gibt es eine Reihe von Feinheiten, die sie besonders schwierig machen. Bevor wir uns mit diesen Feinheiten befassen, erhalten wir zunächst ein GridView-Element, das die Lieferanten auflistet.
Öffnen Sie zunächst die RadioButtonField.aspx
Seite im EnhancedGridView
Ordner, indem Sie ein GridView-Objekt aus der Toolbox auf die Designer ziehen. Legen Sie die GridViews ID
auf fest Suppliers
, und wählen Sie aus dem zugehörigen Smarttag aus, um eine neue Datenquelle zu erstellen. Erstellen Sie insbesondere eine ObjectDataSource mit dem Namen SuppliersDataSource
, die ihre Daten aus dem SuppliersBLL
-Objekt abruft.
Abbildung 4: Erstellen einer neuen ObjectDataSource namens SuppliersDataSource
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 5: Konfigurieren der ObjectDataSource für die Verwendung der SuppliersBLL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Da wir nur diese Lieferanten in den USA auflisten möchten, wählen Sie die GetSuppliersByCountry(country)
Methode aus der Dropdownliste auf der Registerkarte SELECT aus.
Abbildung 6: Konfigurieren der ObjectDataSource für die Verwendung der SuppliersBLL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Wählen Sie auf der Registerkarte UPDATE die Option (Keine) aus, und klicken Sie auf Weiter.
Abbildung 7: Konfigurieren der ObjectDataSource für die Verwendung der SuppliersBLL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Da die GetSuppliersByCountry(country)
-Methode einen Parameter akzeptiert, fordert der Assistent Datenquelle konfigurieren uns zur Eingabe der Quelle dieses Parameters auf. Um einen hartcodierten Wert ( in diesem Beispiel USA) anzugeben, lassen Sie die Dropdownliste Parameterquelle auf Keine festgelegt, und geben Sie den Standardwert in das Textfeld ein. Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen.
Abbildung 8: Verwenden von USA als Standardwert für den country
Parameter (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten enthält GridView ein BoundField für jedes der Lieferantendatenfelder. Entfernen Sie alle außer CompanyName
, City
und Country
BoundFields, und benennen Sie die CompanyName
BoundFields-Eigenschaft HeaderText
in Supplier um. Danach sollte die deklarative Syntax GridView und ObjectDataSource in etwa wie folgt aussehen.
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
<SelectParameters>
<asp:Parameter DefaultValue="USA" Name="country" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
In diesem Tutorial ermöglicht es dem Benutzer, die produkte des ausgewählten Lieferanten auf derselben Seite wie die Lieferantenliste oder auf einer anderen Seite anzuzeigen. Um dies zu berücksichtigen, fügen Sie der Seite zwei Button-Websteuerelemente hinzu. Ich habe die ID
s dieser beiden Schaltflächen auf ListProducts
und SendToProducts
festgelegt, mit der Idee, dass, wenn ListProducts
geklickt wird, ein Postback erfolgt und die ausgewählten Produkte des Lieferanten auf derselben Seite aufgeführt werden, aber wenn SendToProducts
geklickt wird, wird der Benutzer zu einer anderen Seite geführt, auf der die Produkte aufgeführt sind.
Abbildung 9 zeigt das Suppliers
GridView-Steuerelement und die beiden Button Web-Steuerelemente, wenn sie über einen Browser angezeigt werden.
Abbildung 9: Für diese Lieferanten aus den USA sind Ihre Informationen zu Name, Ort und Land aufgeführt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Schritt 3: Hinzufügen einer Spalte mit Optionsfeldern
An diesem Punkt verfügt GridView Suppliers
über drei BoundFields, die den Firmennamen, die Stadt und das Land jedes Anbieters in den USA anzeigen. Es fehlt jedoch immer noch eine Spalte mit Optionsfeldern. Leider enthält gridView kein integriertes RadioButtonField, andernfalls könnten wir das einfach dem Raster hinzufügen und fertig sein. Stattdessen können wir ein TemplateField hinzufügen und dessen ItemTemplate
so konfigurieren, dass ein Optionsfeld gerendert wird, was zu einem Optionsfeld für jede GridView-Zeile führt.
Zunächst kann davon ausgegangen werden, dass die gewünschte Benutzeroberfläche implementiert werden kann, indem ein RadioButton-Websteuerelement zu ItemTemplate
einem TemplateField hinzugefügt wird. Dadurch wird zwar jeder Zeile des GridView-Steuerelements ein einzelnes Optionsfeld hinzugefügt, die Optionsfelder können jedoch nicht gruppiert werden und schließen sich daher nicht gegenseitig aus. Das heißt, ein Endbenutzer kann mehrere Optionsfelder gleichzeitig aus der GridView auswählen.
Obwohl die Verwendung eines TemplateField-Steuerelements von RadioButton-Websteuerelementen nicht die funktionalität bietet, die wir benötigen, sollten wir diesen Ansatz implementieren, da es sich lohnt, zu untersuchen, warum die resultierenden Optionsfelder nicht gruppiert sind. Fügen Sie zunächst der Suppliers GridView ein TemplateField hinzu, sodass es das feld ganz links ist. Klicken Sie als Nächstes im Smarttag von GridView auf den Link Vorlagen bearbeiten, und ziehen Sie ein RadioButton-Websteuerelement aus der Toolbox in die TemplateFields ItemTemplate
(siehe Abbildung 10). Legen Sie die RadioButton-Eigenschaft ID
auf und die GroupName
-Eigenschaft auf SuppliersGroup
RowSelector
fest.
Abbildung 10: Hinzufügen eines RadioButton-Websteuerelements zum ItemTemplate
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nachdem Sie diese Ergänzungen über die Designer gemacht haben, sollte Ihr GridView-Markup in etwa wie folgt aussehen:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButton ID="RowSelector" runat="server"
GroupName="SuppliersGroup" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
Die RadioButton-Eigenschaft wird GroupName
verwendet, um eine Reihe von Optionsfeldern zu gruppieren. Alle RadioButton-Steuerelemente mit demselben GroupName
Wert gelten als gruppiert. Es kann jeweils nur ein Optionsfeld aus einer Gruppe ausgewählt werden. Die GroupName
-Eigenschaft gibt den Wert für das Attribut des gerenderten Optionsfelds an name
. Der Browser untersucht die Optionsfeldattribute name
, um die Optionsfeldgruppierungen zu bestimmen.
Wenn das RadioButton-Websteuerelement hinzugefügt wird ItemTemplate
, besuchen Sie diese Seite über einen Browser, und klicken Sie auf die Optionsfelder in den Zeilen des Rasters. Beachten Sie, dass die Optionsfelder nicht gruppiert sind, sodass sie wie in Abbildung 11 dargestellt alle Zeilen auswählen können.
Abbildung 11: Die GridView-Optionsfelder sind nicht gruppiert (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Der Grund, warum die Optionsfelder nicht gruppiert werden, ist, dass sich ihre gerenderten name
Attribute unterscheiden, obwohl sie dieselbe GroupName
Eigenschaftseinstellung haben. Um diese Unterschiede zu sehen, führen Sie im Browser eine Ansicht/Quelle aus, und untersuchen Sie das Optionsfeldmarkup:
<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector"
name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector"
name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector"
name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector"
name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup"
type="radio" value="RowSelector" />
Beachten Sie, dass sowohl das name
- id
als auch das -Attribut nicht die exakten Werte sind, wie im Eigenschaftenfenster angegeben, sondern mit einer Reihe anderer ID
Werte vorangestellt sind. Die zusätzlichen ID
Werte, die an der Vorderseite des gerenderten id
und name
-Attributs hinzugefügt werden, sind die ID
s der übergeordneten Optionsfelder, die ID
GridViewRow
GridViews ID
, die Inhaltssteuerelemente ID
und die WebFormulare ID
. Diese ID
s werden hinzugefügt, sodass jedes gerenderte Websteuerelement in GridView über einen eindeutigen id
Wert und name
verfügt.
Jedes gerenderte Steuerelement benötigt ein anderes name
, da id
der Browser jedes Steuerelement auf clientseitiger Seite eindeutig identifiziert und wie er dem Webserver identifiziert, welche Aktion oder Änderung beim Postback aufgetreten ist. Angenommen, wir möchten serverseitigen Code immer dann ausführen, wenn ein aktivierter RadioButton-Status geändert wurde. Dies können Sie erreichen, indem Sie die RadioButton-Eigenschaft AutoPostBack
auf true
festlegen und einen Ereignishandler für das CheckChanged
Ereignis erstellen. Wenn jedoch die gerenderten name
Werte und id
für alle Optionsfelder identisch waren, konnten wir beim Postback nicht ermitteln, auf welche bestimmte RadioButton-Taste geklickt wurde.
Kurz gesagt, wir können keine Spalte mit Optionsfeldern in einem GridView-Steuerelement mithilfe des RadioButton-Websteuerelements erstellen. Stattdessen müssen wir eher archaische Techniken verwenden, um sicherzustellen, dass das entsprechende Markup in jede GridView-Zeile eingefügt wird.
Hinweis
Wie das RadioButton-Websteuerelement enthält das OPTIONSFELD-HTML-Steuerelement, wenn es einer Vorlage hinzugefügt wird, das eindeutige name
Attribut, sodass die Optionsfelder im Raster nicht gruppiert werden. Wenn Sie mit HTML-Steuerelementen nicht vertraut sind, können Sie diesen Hinweis ignorieren, da HTML-Steuerelemente nur selten verwendet werden, insbesondere in ASP.NET 2.0. Wenn Sie jedoch mehr erfahren möchten, lesen Sie K. Scott Allens Blogeintrag Websteuerelemente und HTML-Steuerelemente.
Verwenden eines Literalsteuerelements zum Einfügen von Optionsfeldmarkups
Um alle Optionsfelder in GridView ordnungsgemäß zu gruppieren, müssen wir das Markup der Optionsfelder manuell in das ItemTemplate
einfügen. Jedes Optionsfeld benötigt dasselbe name
Attribut, sollte jedoch ein eindeutiges id
Attribut aufweisen (falls wir über clientseitiges Skript auf ein Optionsfeld zugreifen möchten). Nachdem ein Benutzer ein Optionsfeld ausgewählt und die Seite zurückgibt, sendet der Browser den Wert des attributs des ausgewählten Optionsfelds value
zurück. Daher benötigt jedes Optionsfeld ein eindeutiges value
Attribut. Schließlich müssen wir beim Postback sicherstellen, dass das checked
Attribut dem einen ausgewählten Optionsfeld hinzugefügt wird. Andernfalls werden die Optionsfelder, nachdem der Benutzer eine Auswahl getroffen und die Beiträge zurückgibt, in ihren Standardzustand zurückkehren (alle nicht ausgewählt).
Es gibt zwei Ansätze, die verwendet werden können, um Markup auf niedriger Ebene in eine Vorlage einzufügen. Eine besteht darin, eine Mischung aus Markup und Aufrufen von Formatierungsmethoden durchzuführen, die in der CodeBehind-Klasse definiert sind. Diese Technik wurde zuerst im Tutorial Verwenden von TemplateFields im GridView-Steuerelement erläutert. In unserem Fall könnte es in etwa wie folgt aussehen:
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
Hier und GetRadioButtonValue
sind Methoden, GetUniqueRadioButton
die in der CodeBehind-Klasse definiert sind, die die entsprechenden id
Attributwerte und value
für jedes Optionsfeld zurückgegeben haben. Dieser Ansatz eignet sich gut für das Zuweisen der id
Attribute und value
, greift jedoch zu kurz, wenn der checked
Attributwert angegeben werden muss, da die Datenbindungssyntax nur ausgeführt wird, wenn Daten zuerst an gridView gebunden werden. Wenn für GridView der Ansichtszustand aktiviert ist, werden die Formatierungsmethoden daher nur ausgelöst, wenn die Seite zum ersten Mal geladen wird (oder wenn GridView explizit an die Datenquelle zurückgeboundt wird), und daher wird die Funktion, die das checked
Attribut festlegt, beim Postback nicht aufgerufen. Es ist ein ziemlich subtiles Problem und etwas außerhalb des Rahmens dieses Artikels, also werde ich es hier belassen. Ich ermutige Sie jedoch, den oben genannten Ansatz zu versuchen und ihn bis zu dem Punkt durchzuarbeiten, an dem Sie hängen bleiben. Eine solche Übung bringt Sie zwar nicht näher an eine funktionierende Version heran, trägt jedoch dazu bei, ein tieferes Verständnis der GridView und des Datenbindungslebenszyklus zu fördern.
Der andere Ansatz zum Einfügen von benutzerdefiniertem Markup auf niedriger Ebene in eine Vorlage und der Ansatz, den wir für dieses Tutorial verwenden werden, besteht darin, der Vorlage ein Literal-Steuerelement hinzuzufügen. Anschließend kann im GridView-Ereignishandler RowCreated
RowDataBound
programmgesteuert auf das Literal-Steuerelement zugegriffen werden, und seine Text
Eigenschaft ist auf das auszustrahlende Markup festgelegt.
Entfernen Sie zunächst radioButton aus dem TemplateField-Element ItemTemplate
, und ersetzen Sie es durch ein Literal-Steuerelement. Legen Sie das Literal-Steuerelement s ID
auf fest RadioButtonMarkup
.
Abbildung 12: Hinzufügen eines Literalsteuerelements zu (ItemTemplate
Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Erstellen Sie als Nächstes einen Ereignishandler für das GridView-Ereignis RowCreated
. Das RowCreated
Ereignis wird für jede hinzugefügte Zeile einmal ausgelöst, unabhängig davon, ob die Daten an gridView rebound werden oder nicht. Das bedeutet, dass selbst bei einem Postback, wenn die Daten aus dem Ansichtszustand neu geladen werden, das RowCreated
Ereignis weiterhin ausgelöst wird, und dies ist der Grund, warum wir es anstelle von RowDataBound
verwenden (was nur ausgelöst wird, wenn die Daten explizit an das Datenwebsteuerelement gebunden sind).
In diesem Ereignishandler möchten wir nur fortfahren, wenn wir es mit einer Datenzeile zu tun haben. Für jede Datenzeile möchten wir programmgesteuert auf das RadioButtonMarkup
Literal-Steuerelement verweisen und dessen Text
Eigenschaft auf das markup festlegen, das ausgegeben werden soll. Wie der folgende Code zeigt, erstellt das ausgegebene Markup ein Optionsfeld, dessen name
Attribut auf SuppliersGroup
festgelegt ist, dessen id
Attribut auf RowSelectorX
festgelegt ist, wobei X der Index der GridView-Zeile ist und dessen value
Attribut auf den Index der GridView-Zeile festgelegt ist.
protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Grab a reference to the Literal control
Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
// Output the markup except for the "checked" attribute
output.Text = string.Format(
@"<input type="radio" name="SuppliersGroup" " +
@"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex);
}
}
Wenn eine GridView-Zeile ausgewählt wird und ein Postback erfolgt, sind wir an der des SupplierID
ausgewählten Lieferanten interessiert. Daher könnte man denken, dass der Wert jedes Optionsfelds der tatsächliche SupplierID
(und nicht der Index der GridView-Zeile) sein sollte. Dies kann zwar unter bestimmten Umständen funktionieren, aber es wäre ein Sicherheitsrisiko, blind zu akzeptieren und zu SupplierID
verarbeiten. Unsere GridView listet beispielsweise nur die Lieferanten in den USA auf. Wenn die SupplierID
jedoch direkt über das Optionsfeld übergeben wird, was soll verhindern, dass ein verschmittiger Benutzer den wert bearbeitet, der SupplierID
beim Postback zurückgesendet wird? Wenn Sie den Zeilenindex als value
verwenden und dann das SupplierID
On-Postback aus der DataKeys
Auflistung abrufen, können Sie sicherstellen, dass der Benutzer nur einen der Werte verwendet, die SupplierID
einer der GridView-Zeilen zugeordnet sind.
Nachdem Sie diesen Ereignishandlercode hinzugefügt haben, nehmen Sie sich eine Minute Zeit, um die Seite in einem Browser zu testen. Beachten Sie zunächst, dass jeweils nur ein Optionsfeld im Raster ausgewählt werden kann. Wenn Sie jedoch ein Optionsfeld auswählen und auf eine der Schaltflächen klicken, tritt ein Postback auf, und die Optionsfelder rückgängig machen in ihren Ursprünglichen Zustand (d. a. beim Postback ist das ausgewählte Optionsfeld nicht mehr ausgewählt). Um dies zu beheben, müssen wir den RowCreated
Ereignishandler so erweitern, dass er den ausgewählten Optionsfeldindex überprüft, der vom Postback gesendet wird, und das checked="checked"
Attribut dem ausgegebenen Markup der Zeilenindexübereinstimmungen hinzufügt.
Wenn ein Postback auftritt, sendet der Browser das name
und value
des ausgewählten Optionsfelds zurück. Der Wert kann programmgesteuert mit Request.Form["name"]
abgerufen werden. Die Request.Form
-Eigenschaft stellt eine NameValueCollection
bereit, die die Formularvariablen darstellt. Die Formularvariablen sind die Namen und Werte der Formularfelder auf der Webseite und werden immer dann vom Webbrowser zurückgesendet, wenn ein Postback erfolgt. Da das gerenderte name
Attribut der Optionsfelder in gridView ist SuppliersGroup
, sendet der Browser SuppliersGroup=valueOfSelectedRadioButton
beim Zurückschicken der Webseite zurück an den Webserver (zusammen mit den anderen Formularfeldern). Auf diese Informationen kann dann über die Request.Form
-Eigenschaft mit zugegriffen werden: Request.Form["SuppliersGroup"]
.
Da der ausgewählte Optionsfeldindex nicht nur im Ereignishandler, sondern in den RowCreated
Click
Ereignishandlern für die Button-Websteuerelemente bestimmt werden muss, fügen wir der CodeBehind-Klasse eine SuppliersSelectedIndex
Eigenschaft hinzu, die zurückgibt -1
, wenn kein Optionsfeld ausgewählt wurde, und den ausgewählten Index, wenn eines der Optionsfelder ausgewählt ist.
private int SuppliersSelectedIndex
{
get
{
if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
return -1;
else
return Convert.ToInt32(Request.Form["SuppliersGroup"]);
}
}
Nachdem diese Eigenschaft hinzugefügt wurde, wissen wir, dass das checked="checked"
Markup im RowCreated
Ereignishandler hinzugefügt wird, wenn SuppliersSelectedIndex
gleich e.Row.RowIndex
ist. Aktualisieren Sie den Ereignishandler, um diese Logik einzuschließen:
protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Grab a reference to the Literal control
Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
// Output the markup except for the "checked" attribute
output.Text = string.Format(
@"<input type="radio" name="SuppliersGroup" " +
@"id="RowSelector{0}" value="{0}"", e.Row.RowIndex);
// See if we need to add the "checked" attribute
if (SuppliersSelectedIndex == e.Row.RowIndex)
output.Text += @" checked="checked"";
// Add the closing tag
output.Text += " />";
}
}
Mit dieser Änderung bleibt das ausgewählte Optionsfeld nach einem Postback ausgewählt. Nachdem wir nun angeben können, welches Optionsfeld ausgewählt ist, können wir das Verhalten so ändern, dass beim ersten Besuch der Seite das Optionsfeld der ersten GridView-Zeile ausgewählt wurde (anstatt standardmäßig keine Optionsfelder ausgewählt zu haben, was das aktuelle Verhalten ist). Damit das erste Optionsfeld standardmäßig ausgewählt wird, ändern Sie einfach die if (SuppliersSelectedIndex == e.Row.RowIndex)
-Anweisung in die folgende: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0))
.
An diesem Punkt haben wir dem GridView eine Spalte mit gruppierten Optionsfeldern hinzugefügt, mit der eine einzelne GridView-Zeile ausgewählt und über Postbacks hinweg gespeichert werden kann. Als Nächstes zeigen wir die Vom ausgewählten Lieferanten bereitgestellten Produkte an. In Schritt 4 erfahren Sie, wie Sie den Benutzer auf eine andere Seite umleiten und die ausgewählte SupplierID
senden. In Schritt 5 erfahren Sie, wie Sie die produkte des ausgewählten Lieferanten in einer GridView auf derselben Seite anzeigen.
Hinweis
Anstatt ein TemplateField (der Fokus dieses langen Schritts 3) zu verwenden, könnten wir eine benutzerdefinierte DataControlField
Klasse erstellen, die die entsprechende Benutzeroberfläche und Funktionalität rendert. Die DataControlField
-Klasse ist die Basisklasse, von der die Felder BoundField, CheckBoxField, TemplateField und andere integrierte GridView- und DetailsView-Felder abgeleitet werden. Das Erstellen einer benutzerdefinierten DataControlField
Klasse würde bedeuten, dass die Spalte von Optionsfeldern nur mithilfe der deklarativen Syntax hinzugefügt werden könnte, und die Replikation der Funktionalität auf anderen Webseiten und anderen Webanwendungen würde erheblich vereinfacht.
Wenn Sie jedoch jemals benutzerdefinierte, kompilierte Steuerelemente in ASP.NET erstellt haben, wissen Sie, dass dies eine menge Beinarbeit erfordert und eine Vielzahl von Feinheiten und Randfällen mit sich bringt, die sorgfältig behandelt werden müssen. Daher verzichten wir vorerst auf die Implementierung einer Spalte von Optionsfeldern als benutzerdefinierte DataControlField
Klasse und bleiben bei der Option TemplateField. Vielleicht haben wir die Möglichkeit, das Erstellen, Verwenden und Bereitstellen benutzerdefinierter DataControlField
Klassen in einem zukünftigen Tutorial zu erkunden!
Schritt 4: Anzeigen der ausgewählten Produkte des Lieferanten auf einer separaten Seite
Nachdem der Benutzer eine GridView-Zeile ausgewählt hat, müssen die produkte des ausgewählten Lieferanten angezeigt werden. In einigen Fällen möchten wir diese Produkte möglicherweise auf einer separaten Seite anzeigen, in anderen fällen ziehen wir es möglicherweise vor, dies auf derselben Seite zu tun. Sehen wir uns zunächst an, wie die Produkte auf einer separaten Seite angezeigt werden. In Schritt 5 sehen wir uns an, wie Sie eine GridView zu hinzufügen, um RadioButtonField.aspx
die Produkte des ausgewählten Lieferanten anzuzeigen.
Derzeit gibt es zwei Button Web-Steuerelemente auf der Seite ListProducts
und SendToProducts
. Wenn auf die SendToProducts
Schaltfläche geklickt wird, möchten wir den Benutzer an ~/Filtering/ProductsForSupplierDetails.aspx
senden. Diese Seite wurde im Tutorial Master-/Detailfilterung über zwei Seiten erstellt und zeigt die Produkte für den Lieferanten an, dessen SupplierID
Abfragezeichenfolgenfeld mit dem Namen SupplierID
übergeben wird.
Um diese Funktionalität bereitzustellen, erstellen Sie einen Ereignishandler für das SendToProducts
Button-Ereignis Click
. In Schritt 3 haben wir die SuppliersSelectedIndex
-Eigenschaft hinzugefügt, die den Index der Zeile zurückgibt, deren Optionsfeld ausgewählt ist. Die entsprechende SupplierID
kann aus der GridView-Sammlung DataKeys
abgerufen werden, und der Benutzer kann dann mit Response.Redirect("url")
an gesendet ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
werden.
protected void SendToProducts_Click(object sender, EventArgs e)
{
// Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
int supplierID =
Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
Response.Redirect(
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID="
+ supplierID);
}
}
Dieser Code funktioniert wunderbar, solange eines der Optionsfelder aus der GridView ausgewählt ist. Wenn für GridView zunächst keine Optionsfelder ausgewählt sind und der Benutzer auf die SendToProducts
Schaltfläche klickt, SuppliersSelectedIndex
wird -1
eine Ausnahme ausgelöst, da -1
sich außerhalb des Indexbereichs der DataKeys
Auflistung befindet. Dies ist jedoch kein Problem, wenn Sie sich entschieden haben, den RowCreated
Ereignishandler wie in Schritt 3 beschrieben zu aktualisieren, sodass das erste Optionsfeld in gridView anfänglich ausgewählt wird.
Fügen Sie der Seite oberhalb von -1
GridView ein Label Web-Steuerelement hinzu, um den SuppliersSelectedIndex
Wert zu berücksichtigen. Legen Sie die ID
-Eigenschaft auf ChooseSupplierMsg
fest, die CssClass
-Eigenschaft auf Warning
, die EnableViewState
-Eigenschaft und Visible
die -Eigenschaft auf false
, und die - Text
Eigenschaft auf Bitte wählen Sie einen Lieferanten aus dem Raster aus. Die CSS-Klasse Warning
zeigt Text in einer roten, kursiven, fetten, großen Schriftart an und ist in Styles.css
definiert. Durch Festlegen der EnableViewState
Eigenschaften und Visible
auf false
wird die Bezeichnung nur für die Postbacks gerendert, bei denen die Eigenschaft des Steuerelements Visible
programmgesteuert auf true
festgelegt ist.
Abbildung 13: Hinzufügen eines Label-Websteuerelements über gridView (Klicken Sie hier, um ein Bild in voller Größe anzuzeigen)
Erweitern Sie als Nächstes den Click
Ereignishandler, um die ChooseSupplierMsg
Bezeichnung anzuzeigen, wenn SuppliersSelectedIndex
kleiner als 0 (null) ist, und leiten Sie den Benutzer andernfalls zu ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
um.
protected void SendToProducts_Click(object sender, EventArgs e)
{
// make sure one of the radio buttons has been selected
if (SuppliersSelectedIndex < 0)
ChooseSupplierMsg.Visible = true;
else
{
// Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
int supplierID =
Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
Response.Redirect(
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID="
+ supplierID);
}
}
Besuchen Sie die Seite in einem Browser, und klicken Sie auf die SendToProducts
Schaltfläche, bevor Sie einen Lieferanten aus der GridView auswählen. Wie in Abbildung 14 dargestellt, wird hier die ChooseSupplierMsg
Bezeichnung angezeigt. Wählen Sie als Nächstes einen Lieferanten aus, und klicken Sie auf die SendToProducts
Schaltfläche. Dadurch gelangen Sie zu einer Seite, auf der die vom ausgewählten Lieferanten bereitgestellten Produkte aufgeführt sind. Abbildung 15 zeigt die ProductsForSupplierDetails.aspx
Seite, auf der der Lieferant von Bigfoot Breweries ausgewählt wurde.
Abbildung 14: Die ChooseSupplierMsg
Bezeichnung wird angezeigt, wenn kein Lieferant ausgewählt ist (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 15: Die Produkte des ausgewählten Lieferanten werden in ProductsForSupplierDetails.aspx
angezeigt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Schritt 5: Anzeigen der produkte des ausgewählten Lieferanten auf derselben Seite
In Schritt 4 haben wir gesehen, wie der Benutzer auf eine andere Webseite gesendet wird, um die Produkte des ausgewählten Lieferanten anzuzeigen. Alternativ können die Produkte des ausgewählten Lieferanten auf derselben Seite angezeigt werden. Um dies zu veranschaulichen, fügen wir eine weitere GridView hinzu, um RadioButtonField.aspx
die Produkte des ausgewählten Lieferanten anzuzeigen.
Da diese GridView der Produkte nur angezeigt werden soll, wenn ein Lieferant ausgewählt wurde, fügen Sie ein Panel-Websteuerelement unter der Suppliers
GridView hinzu, und legen Sie es ID
auf ProductsBySupplierPanel
und seine Visible
Eigenschaft auf false
fest. Fügen Sie im Bereich den Text Produkte für den ausgewählten Lieferanten hinzu, gefolgt von einer GridView mit dem Namen ProductsBySupplier
. Wählen Sie im Smarttag von GridView aus, um es an eine neue ObjectDataSource mit dem Namen ProductsBySupplierDataSource
zu binden.
Abbildung 16: Binden der ProductsBySupplier
GridView an ein neues ObjectDataSource (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Konfigurieren Sie als Nächstes die ObjectDataSource, um die ProductsBLL
-Klasse zu verwenden. Da wir nur die vom ausgewählten Lieferanten bereitgestellten Produkte abrufen möchten, geben Sie an, dass die ObjectDataSource die GetProductsBySupplierID(supplierID)
Methode aufrufen soll, um die Daten abzurufen. Wählen Sie in den Dropdownlisten auf den Registerkarten UPDATE, INSERT und DELETE die Option (Keine) aus.
Abbildung 17: Konfigurieren der ObjectDataSource für die Verwendung der GetProductsBySupplierID(supplierID)
-Methode (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Abbildung 18: Festlegen der Drop-Down Listen auf (Keine) in den Registerkarten UPDATE, INSERT und DELETE (Klicken, um das bild in voller Größe anzuzeigen)
Klicken Sie nach dem Konfigurieren der Registerkarten SELECT, UPDATE, INSERT und DELETE auf Weiter. Da die GetProductsBySupplierID(supplierID)
Methode einen Eingabeparameter erwartet, fordert uns der Assistent Datenquelle erstellen auf, die Quelle für den Wert des Parameters anzugeben.
Wir haben hier eine Reihe von Optionen, um die Quelle des Werts des Parameters anzugeben. Wir können das Standardobjekt Parameter verwenden und den Wert der SuppliersSelectedIndex
-Eigenschaft programmgesteuert der Parameter s-Eigenschaft DefaultValue
im ObjectDataSource-Ereignishandler Selecting
zuweisen. Im Tutorial Programmgesteuertes Festlegen der Parameterwerte von ObjectDataSource finden Sie eine Aktualisierung zum programmgesteuerten Zuweisen von Werten zu den Parametern von ObjectDataSource.
Alternativ können wir einen ControlParameter verwenden und auf die Eigenschaft GridView Suppliers
verweisenSelectedValue
(siehe Abbildung 19). Die GridView-Eigenschaft SelectedValue
gibt den Wert zurück, der DataKey
der SelectedIndex
Eigenschaft entspricht. Damit diese Option funktioniert, müssen wir die GridView-Eigenschaft SelectedIndex
programmgesteuert auf die ausgewählte Zeile festlegen, wenn auf die ListProducts
Schaltfläche geklickt wird. Als zusätzlichen Vorteil übernimmt SelectedRowStyle
der SelectedIndex
ausgewählte Datensatz das im DataWebControls
Design definierte (gelber Hintergrund).
Abbildung 19: Verwenden eines ControlParameter zum Angeben des GridView-Werts SelectedValue als Parameterquelle (Klicken, um das bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten fügt Visual Studio automatisch Felder für die Datenfelder des Produkts hinzu. Entfernen Sie alle außer , ProductName
CategoryName
und UnitPrice
BoundFields, und ändern Sie die HeaderText
Eigenschaften in Product, Category und Price. Konfigurieren Sie das UnitPrice
BoundField so, dass sein Wert als Währung formatiert ist. Nachdem Sie diese Änderungen vorgenommen haben, sollte das deklarative Markup von Panel, GridView und ObjectDataSource wie folgt aussehen:
<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
<h3>
Products for the Selected Supplier</h3>
<p>
<asp:GridView ID="ProductsBySupplier" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
<SelectParameters>
<asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</p>
</asp:Panel>
Um diese Übung abzuschließen, müssen wir die GridView-Eigenschaft SelectedIndex
auf und SelectedSuppliersIndex
die ProductsBySupplierPanel
Panel-Eigenschaft Visible
auf true
festlegen, wenn auf die ListProducts
Schaltfläche geklickt wird. Erstellen Sie hierzu einen Ereignishandler für das Ereignis des ListProducts
Button-Websteuerelements Click
, und fügen Sie den folgenden Code hinzu:
protected void ListProducts_Click(object sender, EventArgs e)
{
// make sure one of the radio buttons has been selected
if (SuppliersSelectedIndex < 0)
{
ChooseSupplierMsg.Visible = true;
ProductsBySupplierPanel.Visible = false;
}
else
{
// Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex;
// Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = true;
}
}
Wenn kein Lieferant in der GridView ausgewählt wurde, wird die ChooseSupplierMsg
Bezeichnung angezeigt und der ProductsBySupplierPanel
Bereich ausgeblendet. Andernfalls wird, wenn ein Lieferant ausgewählt wurde, angezeigt ProductsBySupplierPanel
, und die GridView-Eigenschaft SelectedIndex
wird aktualisiert.
Abbildung 20 zeigt die Ergebnisse, nachdem der Lieferant der Bigfoot-Brauereien ausgewählt wurde und auf die Schaltfläche Produkte auf Seite anzeigen geklickt wurde.
Abbildung 20: Die von Bigfoot Breweries gelieferten Produkte werden auf derselben Seite aufgeführt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Zusammenfassung
Wie im Tutorial Master/Detail Using a Selectable Master GridView with a Details DetailView erläutert, können Datensätze aus einer GridView mit einem CommandField ausgewählt werden, dessen ShowSelectButton
Eigenschaft auf true
festgelegt ist. Aber das CommandField zeigt seine Schaltflächen entweder als reguläre Drucktasten, Links oder Bilder an. Eine alternative Benutzeroberfläche für die Zeilenauswahl besteht darin, ein Optionsfeld oder Kontrollkästchen in jeder GridView-Zeile bereitzustellen. In diesem Tutorial haben wir untersucht, wie Sie eine Spalte mit Optionsfeldern hinzufügen.
Leider ist das Hinzufügen einer Spalte mit Optionsfeldern nicht so einfach oder einfach, wie man erwarten könnte. Es gibt kein integriertes RadioButtonField, das per Mausklick hinzugefügt werden kann, und die Verwendung des RadioButton-Websteuerelements in einem TemplateField führt zu eigenen Problemen. Um eine solche Schnittstelle bereitzustellen, müssen sie entweder eine benutzerdefinierte DataControlField
Klasse erstellen oder während RowCreated
des Ereignisses den entsprechenden HTML-Code in ein TemplateField-Element einfügen.
Nachdem wir uns mit dem Hinzufügen einer Spalte mit Optionsfeldern beschäftigt haben, sollten wir uns mit dem Hinzufügen einer Spalte mit Kontrollkästchen befassen. Mit einer Spalte mit Kontrollkästchen kann ein Benutzer eine oder mehrere GridView-Zeilen auswählen und dann einen Vorgang für alle ausgewählten Zeilen ausführen (z. B. auswählen einer Reihe von E-Mails aus einem webbasierten E-Mail-Client und anschließendes Löschen aller ausgewählten E-Mails). Im nächsten Tutorial erfahren Sie, wie Sie eine solche Spalte 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 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 David Suru. Möchten Sie meine anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.