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
Erfahren Sie, wie Sie eine vollständig bearbeitbare DataList erstellen, in der sich alle zugehörigen Elemente im Bearbeitungsmodus befinden und deren Werte gespeichert werden können, indem Sie auf der Seite auf eine Schaltfläche "Alle aktualisieren" klicken.
Einleitung
Im vorherigen Lernprogramm haben wir untersucht, wie eine DataList auf Elementebene erstellt wird. Wie bei der standardmäßigen bearbeitbaren GridView enthielt jedes Element in der DataList eine Bearbeitungsschaltfläche, die beim Klicken auf das Element bearbeitbar wäre. Die Bearbeitung auf Elementebene eignet sich zwar gut für Daten, die nur gelegentlich aktualisiert werden, aber bestimmte Anwendungsfallszenarien erfordern, dass der Benutzer viele Datensätze bearbeiten kann. Wenn ein Benutzer Dutzende von Datensätzen bearbeiten muss und gezwungen ist, auf "Bearbeiten" zu klicken, seine Änderungen vorzunehmen und auf "Aktualisieren" zu klicken, kann die Anzahl des Klickens ihre Produktivität beeinträchtigen. In solchen Situationen besteht eine bessere Option darin, eine vollständig bearbeitbare DataList bereitzustellen, bei der sich alle zugehörigen Elemente im Bearbeitungsmodus befinden und deren Werte durch Klicken auf eine Schaltfläche "Alle aktualisieren" auf der Seite bearbeitet werden können (siehe Abbildung 1).
Abbildung 1: Jedes Element in einer vollständig bearbeitbaren DataList kann geändert werden (Klicken, um das Bild in voller Größe anzuzeigen)
In diesem Lernprogramm untersuchen wir, wie Sie Benutzern das Aktualisieren von Lieferantenadresseninformationen mithilfe einer vollständig bearbeitbaren DataList ermöglichen.
Schritt 1: Erstellen der bearbeitbaren Benutzeroberfläche in der DataList s ItemTemplate
Im vorherigen Lernprogramm, in dem wir eine standardmäßige, bearbeitbare DataList auf Elementebene erstellen, haben wir zwei Vorlagen verwendet:
-
ItemTemplate
enthält die Benutzeroberfläche im Nur-Lese-Modus (die Label-Websteuerelemente zum Anzeigen von Produktnamen und -preisen). -
EditItemTemplate
enthält die Benutzeroberfläche des Bearbeitungsmodus (die beiden TextBox-Websteuerelemente).
Die DataList-Eigenschaft EditItemIndex
regelt, welches DataListItem
(sofern vorhanden) mithilfe von EditItemTemplate
gerendert wird. Insbesondere wird das DataListItem
, dessen ItemIndex
mit der DataList-Eigenschaft EditItemIndex
übereinstimmt, mithilfe von EditItemTemplate
gerendert. Dieses Modell funktioniert gut, wenn jeweils nur ein Element bearbeitet werden kann, aber beim Erstellen einer vollständig bearbeitbaren DataList auseinanderfällt.
Für eine vollständig bearbeitbare DataList möchten wir, dass alleDataListItem
Elemente mithilfe der bearbeitbaren Schnittstelle gerendert werden. Die einfachste Möglichkeit, dies zu erreichen, ist das Definieren der bearbeitbaren Schnittstelle in der ItemTemplate
. Zum Ändern der Adressinformationen der Lieferanten enthält die bearbeitbare Schnittstelle den Lieferantennamen als Text und dann TextBoxes für die Werte "Adresse", "Ort" und "Land/Region".
Öffnen Sie zunächst die BatchUpdate.aspx
Seite, fügen Sie ein DataList-Steuerelement hinzu, und legen Sie dessen ID
Eigenschaft auf Suppliers
. Wählen Sie im Smarttag "DataList" die Option, ein neues ObjectDataSource-Steuerelement mit dem Namen SuppliersDataSource
hinzuzufügen.
Abbildung 2: Erstellen einer neuen ObjectDataSource namens SuppliersDataSource
(Klicken Sie, um das Bild in voller Größe anzuzeigen)
Konfigurieren Sie objectDataSource so, dass Daten mithilfe der SuppliersBLL
Klassenmethode GetSuppliers()
abgerufen werden (siehe Abbildung 3). Wie im vorherigen Lernprogramm arbeiten wir, anstatt die Lieferanteninformationen über ObjectDataSource zu aktualisieren, direkt mit der Geschäftslogikebene zusammen. Legen Sie daher die Dropdownliste auf (Keine) auf der Registerkarte UPDATE fest (siehe Abbildung 4).
Abbildung 3: Abrufen von Lieferanteninformationen mithilfe der GetSuppliers()
Methode (Klicken, um das Bild in voller Größe anzuzeigen)
Abbildung 4: Festlegen der Drop-Down Liste auf (Keine) auf der Registerkarte "AKTUALISIEREN" (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten generiert Visual Studio automatisch die DataLists ItemTemplate
, um jedes von der Datenquelle zurückgegebene Datenfeld in einem Label-Websteuerelement anzuzeigen. Wir müssen diese Vorlage so ändern, dass sie stattdessen die Bearbeitungsschnittstelle bereitstellt. Dies ItemTemplate
kann über den Designer mithilfe der Option "Vorlagen bearbeiten" aus dem Smarttag von DataList oder direkt über die deklarative Syntax angepasst werden.
Nehmen Sie sich einen Moment Zeit, um eine Bearbeitungsschnittstelle zu erstellen, die den Namen des Lieferanten als Text anzeigt, aber TextBoxes für die Adress-, Orts- und Länder-/Regionswerte des Lieferanten enthält. Nachdem Sie diese Änderungen vorgenommen haben, sollte die deklarative Syntax Ihrer Seite wie folgt aussehen:
<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
DataSourceID="SuppliersDataSource">
<ItemTemplate>
<h4><asp:Label ID="CompanyNameLabel" runat="server"
Text='<%# Eval("CompanyName") %>' /></h4>
<table border="0">
<tr>
<td class="SupplierPropertyLabel">Address:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="Address" runat="server"
Text='<%# Eval("Address") %>' />
</td>
</tr>
<tr>
<td class="SupplierPropertyLabel">City:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="City" runat="server"
Text='<%# Eval("City") %>' />
</td>
</tr>
<tr>
<td class="SupplierPropertyLabel">Country:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="Country" runat="server"
Text='<%# Eval("Country") %>' />
</td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>
Hinweis
Wie im vorherigen Lernprogramm muss die DataList in diesem Lernprogramm den Ansichtsstatus aktiviert haben.
In der ItemTemplate
verwende ich zwei neue CSS-Klassen, SupplierPropertyLabel
und SupplierPropertyValue
, die zur Styles.css
-Klasse hinzugefügt und so konfiguriert wurden, dass sie die gleichen Stil-Einstellungen wie die CSS-Klassen ProductPropertyLabel
und ProductPropertyValue
nutzen.
.ProductPropertyLabel, .SupplierPropertyLabel
{
font-weight: bold;
text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
padding-right: 35px;
}
Nachdem Sie diese Änderungen vorgenommen haben, besuchen Sie diese Seite über einen Browser. Wie in Abbildung 5 dargestellt, zeigt jedes DataList-Element den Lieferantennamen als Text an und verwendet TextBoxes zum Anzeigen der Adresse, des Orts und der Region.
Abbildung 5: Jeder Lieferant in der DataList ist bearbeitbar (Zum Anzeigen des Bilds mit voller Größe klicken)
Schritt 2: Hinzufügen einer Schaltfläche "Alle aktualisieren"
Während jeder Lieferant in Abbildung 5 die Felder "Adresse", "Ort" und "Land/Region" in einem TextBox-Element anzeigt, ist derzeit keine Schaltfläche "Aktualisieren" verfügbar. Anstatt eine Schaltfläche "Aktualisieren" pro Element zu haben, gibt es in der Regel eine einzelne Schaltfläche "Aktualisieren Alle" auf der Seite, die, wenn sie angeklickt wird, alle Datensätze in der DataList aktualisiert. In diesem Lernprogramm fügen wir zwei Schaltflächen "Alle aktualisieren" hinzu – eine am oberen Rand der Seite und eine am unteren Rand (obwohl das Klicken auf eine der Schaltflächen denselben Effekt hat).
Fügen Sie zunächst ein Schaltflächenweb-Steuerelement oberhalb der DataList hinzu, und legen Sie dessen ID
Eigenschaft auf UpdateAll1
. Fügen Sie als Nächstes das zweite Schaltflächen-Websteuerelement unter der DataList hinzu, und setzen Sie es ID
auf UpdateAll2
. Legen Sie die Text
Eigenschaften für die beiden Schaltflächen auf "Alle aktualisieren" fest. Erstellen Sie schließlich Ereignishandler für die Ereignisse beider Schaltflächen Click
. Anstatt die Aktualisierungslogik in jedem der Ereignishandler zu duplizieren, lassen Sie uns diese Logik in eine dritte Methode umgestalten, UpdateAllSupplierAddresses
wobei die Ereignishandler einfach diese dritte Methode aufrufen.
protected void UpdateAll1_Click(object sender, EventArgs e)
{
UpdateAllSupplierAddresses();
}
protected void UpdateAll2_Click(object sender, EventArgs e)
{
UpdateAllSupplierAddresses();
}
private void UpdateAllSupplierAddresses()
{
// TODO: Write code to update _all_ of the supplier addresses in the DataList
}
Abbildung 6 zeigt die Seite, nachdem die Schaltflächen "Alle aktualisieren" hinzugefügt wurden.
Abbildung 6: Zwei 'Alles aktualisieren' Schaltflächen wurden zur Seite hinzugefügt (Klicken, um das Bild in voller Größe anzuzeigen)
Schritt 3: Aktualisieren aller Adressinformationen der Lieferanten
Bei allen DataList-Elementen, die die Bearbeitungsoberfläche anzeigen, und der Hinzufügung der Schaltfläche "Alle aktualisieren" bleibt nur noch, den Code für die Batchaktualisierung zu schreiben. Insbesondere müssen wir die Elemente der DataList durchlaufen und für jedes die SuppliersBLL
-Klasse-UpdateSupplierAddress
-Methode aufrufen.
Auf die Sammlung von DataListItem
Instanzen, die die DataList erstellen, kann über die DataList-Eigenschaft Items
zugegriffen werden. Mit einem Verweis auf ein DataListItem
Objekt können wir das entsprechende SupplierID
aus der DataKeys
Auflistung abrufen und programmgesteuert auf die TextBox-Websteuerelemente innerhalb des ItemTemplate
wie im folgenden Code gezeigt verweisen:
private void UpdateAllSupplierAddresses()
{
// Create an instance of the SuppliersBLL class
SuppliersBLL suppliersAPI = new SuppliersBLL();
// Iterate through the DataList's items
foreach (DataListItem item in Suppliers.Items)
{
// Get the supplierID from the DataKeys collection
int supplierID = Convert.ToInt32(Suppliers.DataKeys[item.ItemIndex]);
// Read in the user-entered values
TextBox address = (TextBox)item.FindControl("Address");
TextBox city = (TextBox)item.FindControl("City");
TextBox country = (TextBox)item.FindControl("Country");
string addressValue = null, cityValue = null, countryValue = null;
if (address.Text.Trim().Length > 0)
addressValue = address.Text.Trim();
if (city.Text.Trim().Length > 0)
cityValue = city.Text.Trim();
if (country.Text.Trim().Length > 0)
countryValue = country.Text.Trim();
// Call the SuppliersBLL class's UpdateSupplierAddress method
suppliersAPI.UpdateSupplierAddress
(supplierID, addressValue, cityValue, countryValue);
}
}
Wenn der Benutzer auf eine der Schaltflächen "Alle aktualisieren" klickt, durchläuft die UpdateAllSupplierAddresses
-Methode jede DataListItem
in der Suppliers
-DataList und ruft die SuppliersBLL
-Methode der UpdateSupplierAddress
-Klasse auf, wobei die entsprechenden Werte übergeben werden. Ein nicht eingegebener Wert für Adress-, Orts- oder Länder-/Regionsdurchläufe ist ein Wert von Nothing
( UpdateSupplierAddress
anstelle einer leeren Zeichenfolge), der zu einer Datenbank NULL
für die zugrunde liegenden Datensatzfelder führt.
Hinweis
Als Erweiterung möchten Sie der Seite möglicherweise ein Statusbezeichnung-Websteuerelement hinzufügen, das nach der Batchaktualisierung eine Bestätigungsmeldung bereitstellt.
Aktualisieren nur der Adressen, die geändert wurden
Der für dieses Lernprogramm verwendete Batchaktualisierungsalgorithmus ruft die UpdateSupplierAddress
Methode für jeden Lieferanten in der DataList auf, unabhängig davon, ob ihre Adressinformationen geändert wurden. Während solche Blindupdates in der Regel kein Leistungsproblem sind, können sie zu überflüssigen Datensätzen führen, wenn Sie Änderungen an der Datenbanktabelle überwachen. Wenn Sie beispielsweise Trigger verwenden, um alle UPDATE
-Einträge in der Suppliers
-Tabelle in einer Audit-Tabelle aufzuzeichnen, wird jedes Mal, wenn ein Benutzer auf die Schaltfläche "Alle aktualisieren" klickt, für jeden Lieferanten im System ein neuer Audit-Datensatz erstellt, unabhängig davon, ob der Benutzer Änderungen vorgenommen hat.
Die ADO.NET DataTable- und DataAdapter-Klassen sind so konzipiert, dass Batchaktualisierungen unterstützt werden, bei denen nur geänderte, gelöschte und neue Datensätze zu einer beliebigen Datenbankkommunikation führen. Jede Zeile in der DataTable weist eine RowState
Eigenschaft auf, die angibt, ob die Zeile der DataTable hinzugefügt, daraus gelöscht, geändert oder unverändert bleibt. Wenn eine DataTable anfangs aufgefüllt wird, werden alle Zeilen unverändert markiert. Wenn Sie den Wert einer der Zeilenspalten ändern, wird die Zeile als geändert markiert.
In der SuppliersBLL
Klasse aktualisieren wir die angegebenen Adressinformationen des Lieferanten, indem wir zuerst den Datensatz des einzelnen Lieferanten in einen SuppliersDataTable
einlesen und dann die Werte der Spalten Address
, City
und Country
mithilfe des folgenden Codes festlegen.
public bool UpdateSupplierAddress
(int supplierID, string address, string city, string country)
{
Northwind.SuppliersDataTable suppliers =
Adapter.GetSupplierBySupplierID(supplierID);
if (suppliers.Count == 0)
// no matching record found, return false
return false;
else
{
Northwind.SuppliersRow supplier = suppliers[0];
if (address == null)
supplier.SetAddressNull();
else
supplier.Address = address;
if (city == null)
supplier.SetCityNull();
else
supplier.City = city;
if (country == null)
supplier.SetCountryNull();
else
supplier.Country = country;
// Update the supplier Address-related information
int rowsAffected = Adapter.Update(supplier);
// Return true if precisely one row was updated,
// otherwise false
return rowsAffected == 1;
}
}
Dieser Code weist naiv die übergebenen Adress-, Orts- und Länder-/Regionswerte den Platzhaltern SuppliersRow
im SuppliersDataTable
zu, unabhängig davon, ob sich die Werte geändert haben. Diese Änderungen bewirken, dass die Eigenschaft SuppliersRow
s RowState
als geändert markiert wird. Wenn die Data Access Layer-Methode Update
aufgerufen wird, sieht sie, dass die SupplierRow
Änderung erfolgt ist und sendet daher einen UPDATE
Befehl an die Datenbank.
Stellen Sie sich jedoch vor, dass wir dieser Methode Code hinzugefügt haben, um nur die übergebenen Adress-, Orts- und Länder-/Regionswerte zuzuweisen, wenn sie sich von den SuppliersRow
vorhandenen Werten unterscheiden. Wenn die Adresse, die Stadt und die Region mit den vorhandenen Daten identisch sind, werden keine Änderungen vorgenommen, und die SupplierRow
Daten RowState
werden unverändert markiert. Das Nettoergebnis ist, dass beim Aufrufen der DAL-Methode Update
kein Datenbankaufruf erfolgt, da die SuppliersRow
Methode nicht geändert wurde.
Um diese Änderung umzusetzen, ersetzen Sie die Anweisungen im Code, die unüberlegt die übergebenen Adress-, Orts- und Länder-/Regionswerte zuweisen, mit dem folgenden Code:
// Only assign the values to the SupplierRow's column values if they differ
if (address == null && !supplier.IsAddressNull())
supplier.SetAddressNull();
else if ((address != null && supplier.IsAddressNull()) ||
(!supplier.IsAddressNull() &&
string.Compare(supplier.Address, address) != 0))
supplier.Address = address;
if (city == null && !supplier.IsCityNull())
supplier.SetCityNull();
else if ((city != null && supplier.IsCityNull()) ||
(!supplier.IsCityNull() && string.Compare(supplier.City, city) != 0))
supplier.City = city;
if (country == null && !supplier.IsCountryNull())
supplier.SetCountryNull();
else if ((country != null && supplier.IsCountryNull()) ||
(!supplier.IsCountryNull() &&
string.Compare(supplier.Country, country) != 0))
supplier.Country = country;
Mit diesem hinzugefügten Code sendet die DAL-Methode Update
eine UPDATE
Anweisung an die Datenbank nur für die Datensätze, bei denen sich die adressbezogenen Werte geändert haben.
Alternativ können wir nachverfolgen, ob es Unterschiede zwischen den übergebenen Adressfeldern und den Datenbankdaten gibt. Wenn keines vorhanden ist, umgehen Sie einfach den Aufruf der DAL s-Methode Update
. Dieser Ansatz funktioniert gut, wenn Sie die Direkte DB-Methode verwenden, da der Direkten DB-Methode keine SuppliersRow
-Instanz übergeben wird, deren RowState
überprüft werden kann, um festzustellen, ob ein Datenbankaufruf tatsächlich benötigt wird.
Hinweis
Jedes Mal, wenn die UpdateSupplierAddress
Methode aufgerufen wird, wird ein Aufruf der Datenbank ausgeführt, um Informationen zum aktualisierten Datensatz abzurufen. Wenn dann Änderungen an den Daten vorliegen, wird ein weiterer Aufruf der Datenbank vorgenommen, um die Tabellenzeile zu aktualisieren. Dieser Workflow kann optimiert werden, indem eine UpdateSupplierAddress
Methodenüberladung erstellt wird, die eine EmployeesDataTable
Instanz akzeptiert, die alle Änderungen von der BatchUpdate.aspx
Seite enthält. Anschließend könnte die Datenbank einen Aufruf ausführen, um alle Datensätze aus der Suppliers
Tabelle abzurufen. Die beiden Resultsets können dann aufgezählt werden, und nur die Datensätze, in denen Änderungen vorgenommen wurden, konnten aktualisiert werden.
Zusammenfassung
In diesem Lernprogramm haben wir erfahren, wie Sie eine vollständig bearbeitbare DataList erstellen, sodass ein Benutzer die Adressinformationen für mehrere Lieferanten schnell ändern kann. Wir begannen damit, die Bearbeitungsschnittstelle mit einem TextBox-Websteuerelement für die Adressen, Stadt und Länder/Region des Lieferanten im DataListItemTemplate
zu definieren. Als Nächstes haben wir oben und unterhalb der DataList "Alle aktualisieren"-Schaltflächen hinzugefügt. Nachdem ein Benutzer seine Änderungen vorgenommen und auf eine der Schaltflächen "Alle aktualisieren" geklickt hat, werden die DataListItem
Elemente aufgezählt, und ein Aufruf der Methode der SuppliersBLL
Klasse UpdateSupplierAddress
erfolgt.
Glückliche Programmierung!
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. Leitende Prüfer für dieses Lernprogramm waren Zack Jones und Ken Pespisa. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.