Share via


Hinzufügen von clientseitiger Bestätigung beim Löschen (C#)

von Scott Mitchell

PDF herunterladen

In den schnittstellen, die wir bisher erstellt haben, kann ein Benutzer versehentlich Daten löschen, indem er auf die Schaltfläche Löschen klickt, wenn er auf die Schaltfläche Bearbeiten klicken wollte. In diesem Tutorial fügen wir ein clientseitiges Bestätigungsdialogfeld hinzu, das angezeigt wird, wenn auf die Schaltfläche Löschen geklickt wird.

Einführung

In den letzten Tutorials haben wir erfahren, wie Sie unsere Anwendungsarchitektur, ObjectDataSource und die Datenwebsteuerelemente gemeinsam verwenden, um Einfüge-, Bearbeitungs- und Löschfunktionen bereitzustellen. Die Löschschnittstellen, die wir bisher untersucht haben, bestehen aus einer Schaltfläche Löschen, die beim Klicken ein Postback auslöst und die ObjectDataSource-Methode Delete() aufruft. Die Delete() -Methode ruft dann die konfigurierte Methode von der Geschäftslogikebene auf, die den Aufruf an die Datenzugriffsebene weitergibt und die eigentliche DELETE Anweisung an die Datenbank ausgibt.

Obwohl diese Benutzeroberfläche es Besuchern ermöglicht, Datensätze über die Steuerelemente GridView, DetailsView oder FormView zu löschen, fehlt jede Bestätigung, wenn der Benutzer auf die Schaltfläche Löschen klickt. Wenn ein Benutzer versehentlich auf die Schaltfläche Löschen klickt, wenn er auf Bearbeiten klicken wollte, wird stattdessen der Datensatz gelöscht, den er aktualisieren wollte. Um dies zu verhindern, fügen wir in diesem Tutorial ein clientseitiges Bestätigungsdialogfeld hinzu, das angezeigt wird, wenn auf die Schaltfläche Löschen geklickt wird.

Die JavaScript-Funktion confirm(string) zeigt ihren Zeichenfolgeneingabeparameter als Text in einem modalen Dialogfeld an, das mit zwei Schaltflächen ausgestattet ist: OK und Abbrechen (siehe Abbildung 1). Die confirm(string) Funktion gibt einen booleschen Wert zurück, je nachdem, auf welche Schaltfläche geklickt wird (truewenn der Benutzer auf OK klickt und false ob er auf Abbrechen klickt).

Die JavaScript-Methode confirm(string) zeigt ein modales meldungsfeld Client-Side an.

Abbildung 1: Die JavaScript-Methode confirm(string) zeigt ein modales Client-Side Messagebox an.

Wenn während einer Formularübermittlung ein Wert von false von von einem clientseitigen Ereignishandler zurückgegeben wird, wird die Formularübermittlung abgebrochen. Mit diesem Feature können wir den Client-Handler onclick der Schaltfläche Löschen den Wert eines Aufrufs von confirm("Are you sure you want to delete this product?")zurückgeben lassen. Wenn der Benutzer auf Abbrechen klickt, confirm(string) gibt false zurück, wodurch die Formularübermittlung abgebrochen wird. Ohne Postback wird das Produkt, dessen Schaltfläche Löschen geklickt wurde, nicht gelöscht. Wenn der Benutzer jedoch im Bestätigungsdialogfeld auf OK klickt, wird das Postback unverändert fortgesetzt, und das Produkt wird gelöscht. Weitere Informationen zu diesem Verfahren finden Sie unter Verwenden der JavaScript-Methode confirm() zum Steuern der Formularübermittlung .

Das Hinzufügen des erforderlichen clientseitigen Skripts unterscheidet sich bei Verwendung von Vorlagen geringfügig von der verwendung eines CommandField. Daher sehen wir uns in diesem Tutorial sowohl ein FormView- als auch ein GridView-Beispiel an.

Hinweis

Bei der Verwendung von clientseitigen Bestätigungstechniken wie den in diesem Tutorial erläuterten wird davon ausgegangen, dass Ihre Benutzer browserseitig besuchen, die JavaScript unterstützen, und dass JavaScript aktiviert ist. Wenn eine dieser Annahmen für einen bestimmten Benutzer nicht zutrifft, führt das Klicken auf die Schaltfläche Löschen sofort zu einem Postback (ohne Anzeige eines Bestätigungsmeldungsfelds).

Schritt 1: Erstellen einer FormView, die das Löschen unterstützt

Fügen Sie zunächst eine FormView zur ConfirmationOnDelete.aspx Seite im EditInsertDelete Ordner hinzu, und binden Sie sie an eine neue ObjectDataSource, die die Produktinformationen über die s-Methode der ProductsBLL Klasse GetProducts() zurückzieht. Konfigurieren Sie außerdem die ObjectDataSource so, dass die ProductsBLL Klasse s-Methode DeleteProduct(productID) der ObjectDataSource-Methode Delete() zugeordnet wird. Stellen Sie sicher, dass die Dropdownlisten INSERT und UPDATE auf (None) festgelegt sind. Aktivieren Sie abschließend das Kontrollkästchen Paging aktivieren im Smarttag von FormView.

Nach diesen Schritten sieht das neue deklarative Markup von ObjectDataSource wie folgt aus:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    DeleteMethod="DeleteProduct" OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <DeleteParameters>
        <asp:Parameter Name="productID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Wie in unseren früheren Beispielen, die keine optimistische Parallelität verwendet haben, nehmen Sie sich einen Moment Zeit, um die ObjectDataSource-Eigenschaft zu OldValuesParameterFormatString löschen.

Da es an ein ObjectDataSource-Steuerelement gebunden wurde, das nur das Löschen unterstützt, bietet die FormView nur ItemTemplate die Schaltfläche Löschen, ohne die Schaltflächen Neu und Aktualisieren. Das deklarative Markup von FormView enthält jedoch ein überflüssiges EditItemTemplate und InsertItemTemplate, das entfernt werden kann. Nehmen Sie sich einen Moment Zeit, um die ItemTemplate anzupassen, sodass nur eine Teilmenge der Produktdatenfelder angezeigt wird. Ich habe meine so konfiguriert, dass der Produktname in einer <h3> Überschrift oberhalb des Lieferanten- und Kategorienamens angezeigt wird (zusammen mit der Schaltfläche Löschen).

<asp:FormView ID="FormView1" AllowPaging="True" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" runat="server">
    <ItemTemplate>
        <h3><i><%# Eval("ProductName") %></i></h3>
        <b>Category:</b>
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'>
        </asp:Label><br />
        <b>Supplier:</b>
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'>
        </asp:Label><br />
        <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
            CommandName="Delete" Text="Delete">
        </asp:LinkButton>
    </ItemTemplate>
</asp:FormView>

Mit diesen Änderungen haben wir eine voll funktionsfähige Webseite, die es einem Benutzer ermöglicht, die Produkte einzeln zu durchlaufen, mit der Möglichkeit, ein Produkt zu löschen, indem er einfach auf die Schaltfläche Löschen klickt. Abbildung 2 zeigt einen Screenshot des bisherigen Fortschritts, wenn es über einen Browser angezeigt wird.

Die FormView zeigt Informationen zu einem einzelnen Produkt an.

Abbildung 2: Die FormView zeigt Informationen zu einem einzelnen Produkt an (Klicken Sie hier, um ein Bild in voller Größe anzuzeigen)

Schritt 2: Aufrufen der confirm(string)-Funktion über das Client-Side onclick-Ereignis

Nachdem die FormView erstellt wurde, besteht der letzte Schritt darin, die Schaltfläche Löschen so zu konfigurieren, dass die JavaScript-Funktion confirm(string) aufgerufen wird, wenn der Besucher darauf klickt. Das Hinzufügen eines clientseitigen Skripts zu einem clientseitigen onclick Button-, LinkButton- oder ImageButton-Ereignis kann mithilfe von OnClientClick propertyerreicht werden, das in ASP.NET 2.0 neu ist. Da der Wert der confirm(string) Funktion zurückgegeben werden soll, legen Sie diese Eigenschaft einfach auf fest: return confirm('Are you certain that you want to delete this product?');

Nach dieser Änderung sollte die deklarative Syntax von Delete LinkButton in etwa wie folgt aussehen:

<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
    CommandName="Delete" Text="Delete"
    OnClientClick="return confirm('Are you certain you want to delete this product?');">
</asp:LinkButton>

Das ist alles, was es gibt! Abbildung 3 zeigt einen Screenshot dieser Bestätigung in Aktion. Wenn Sie auf die Schaltfläche Löschen klicken, wird das Bestätigungsdialogfeld angezeigt. Wenn der Benutzer auf Abbrechen klickt, wird das Postback abgebrochen, und das Produkt wird nicht gelöscht. Wenn der Benutzer jedoch auf OK klickt, wird das Postback fortgesetzt, und die ObjectDataSource-Methode Delete() wird aufgerufen, was dazu führt, dass der Datenbankdatensatz gelöscht wird.

Hinweis

Die an die confirm(string) JavaScript-Funktion übergebene Zeichenfolge wird durch Apostrophe (anstelle von Anführungszeichen) getrennt. In JavaScript können Zeichenfolgen mit einem zeichen getrennt werden. Wir verwenden hier Apostrophe, damit die Trennzeichen für die übergebene confirm(string) Zeichenfolge keine Mehrdeutigkeit mit den Für den OnClientClick Eigenschaftswert verwendeten Trennzeichen aufweisen.

Beim Klicken auf die Schaltfläche

Abbildung 3: Beim Klicken auf die Schaltfläche "Löschen" wird jetzt eine Bestätigung angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Schritt 3: Konfigurieren der OnClientClick-Eigenschaft für die Schaltfläche "Löschen" in einem CommandField

Wenn Sie mit einem Button, LinkButton oder ImageButton direkt in einer Vorlage arbeiten, kann ihm ein Bestätigungsdialogfeld zugeordnet werden, indem die -Eigenschaft einfach so konfiguriert OnClientClick wird, dass die Ergebnisse der JavaScript-Funktion confirm(string) zurückgegeben werden. Das CommandField, das einem GridView- oder DetailsView-Objekt ein Feld mit Schaltflächen zum Löschen hinzufügt, verfügt jedoch nicht über eine OnClientClick Eigenschaft, die deklarativ festgelegt werden kann. Stattdessen müssen wir programmgesteuert auf die Schaltfläche Löschen im entsprechenden DataBound GridView- oder DetailsView-Ereignishandler verweisen und dann ihre -Eigenschaft dort festlegen OnClientClick .

Hinweis

Beim Festlegen der Eigenschaft Schaltfläche löschen OnClientClick im entsprechenden DataBound Ereignishandler haben wir Zugriff auf die Daten, die an den aktuellen Datensatz gebunden wurden. Dies bedeutet, dass wir die Bestätigungsmeldung erweitern können, um Details zum jeweiligen Datensatz zu enthalten, z. B. "Möchten Sie das Chai-Produkt wirklich löschen?" Eine solche Anpassung ist auch in Vorlagen mit Datenbindungssyntax möglich.

Um das Festlegen der OnClientClick Eigenschaft für die Schaltflächen "Löschen" in einem CommandField zu üben, fügen Sie der Seite ein GridView-Element hinzu. Konfigurieren Sie dieses GridView so, dass dasselbe ObjectDataSource-Steuerelement verwendet wird, das auch von FormView verwendet wird. Beschränken Sie außerdem die BoundFields von GridView so, dass sie nur den Namen, die Kategorie und den Lieferanten des Produkts enthalten. Aktivieren Sie abschließend das Kontrollkästchen Löschen aktivieren im Smarttag von GridView. Dadurch wird der GridView-Auflistung Columns ein CommandField hinzugefügt, dessen ShowDeleteButton -Eigenschaft auf truefestgelegt ist.

Nachdem Sie diese Änderungen vorgenommen haben, sollte Ihr deklaratives GridView-Markup wie folgt aussehen:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True"
            SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True"
            SortExpression="SupplierName" />
    </Columns>
</asp:GridView>

CommandField enthält eine einzelne Delete LinkButton-instance, auf die programmgesteuert über den GridView-Ereignishandler RowDataBound zugegriffen werden kann. Sobald darauf verwiesen wird, können wir die - OnClientClick Eigenschaft entsprechend festlegen. Erstellen Sie mit dem folgenden Code einen Ereignishandler für das RowDataBound Ereignis:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // reference the Delete LinkButton
        LinkButton db = (LinkButton)e.Row.Cells[0].Controls[0];

        // Get information about the product bound to the row
        Northwind.ProductsRow product =
            (Northwind.ProductsRow) ((System.Data.DataRowView) e.Row.DataItem).Row;

        db.OnClientClick = string.Format(
            "return confirm('Are you certain you want to delete the {0} product?');",
            product.ProductName.Replace("'", @"\'"));
    }
}

Dieser Ereignishandler arbeitet mit Datenzeilen (die über die Schaltfläche Löschen verfügen) und verweist zunächst programmgesteuert auf die Schaltfläche Löschen. Verwenden Sie im Allgemeinen das folgende Muster:

ButtonType obj = (ButtonType) e.Row.Cells[commandFieldIndex].Controls[controlIndex];

ButtonType ist der Typ der Schaltfläche, die von CommandField – Button, LinkButton oder ImageButton verwendet wird. Standardmäßig verwendet das CommandField LinkButtons, dies kann jedoch über commandField angepasst ButtonType propertywerden. CommandFieldIndex ist der Ordnungsindex des CommandField innerhalb der GridView-AuflistungColumns, während controlIndex der Index der Schaltfläche Löschen in der CommandField s-Auflistung Controls ist. Der controlIndex-Wert hängt von der Position der Schaltfläche relativ zu anderen Schaltflächen im CommandField ab. Wenn beispielsweise die einzige schaltfläche, die im CommandField angezeigt wird, die Schaltfläche Löschen ist, verwenden Sie den Index 0. Wenn jedoch eine Schaltfläche Bearbeiten vorhanden ist, die der Schaltfläche Löschen vorangestellt ist, verwenden Sie den Index 2. Der Grund dafür, dass ein Index von 2 verwendet wird, liegt daran, dass zwei Steuerelemente vom CommandField vor der Schaltfläche Löschen hinzugefügt werden: die Schaltfläche Bearbeiten und ein LiteralControl, das verwendet wird, um zwischen den Schaltflächen Bearbeiten und Löschen Platz hinzuzufügen.

Für unser spezielles Beispiel verwendet das CommandField LinkButtons und weist als feld am weitesten links den commandFieldIndex-Wert 0 auf. Da es keine anderen Schaltflächen außer der Schaltfläche Löschen im CommandField gibt, verwenden wir den controlIndex-Wert 0.

Nachdem wir auf die Schaltfläche Löschen im CommandField verwiesen haben, werden als Nächstes Informationen zum Produkt erfasst, das an die aktuelle GridView-Zeile gebunden ist. Schließlich legen wir die Eigenschaft Schaltfläche löschen OnClientClick auf das entsprechende JavaScript fest, das den Namen des Produkts enthält. Da die an die confirm(string) Funktion übergebene JavaScript-Zeichenfolge durch Apostrophe getrennt wird, müssen wir alle Apostrophe mit Escapezeichen versehen, die innerhalb des Produktnamens angezeigt werden. Insbesondere werden alle Apostrophe im Produktnamen mit "\'" versehen.

Wenn diese Änderungen abgeschlossen sind, wird beim Klicken auf die Schaltfläche Löschen in GridView ein benutzerdefiniertes Bestätigungsdialogfeld angezeigt (siehe Abbildung 4). Wie beim Bestätigungsmeldungsfeld aus der FormView wird das Postback abgebrochen, wenn der Benutzer auf Abbrechen klickt, wodurch das Löschen verhindert wird.

Hinweis

Diese Technik kann auch verwendet werden, um programmgesteuert auf die Schaltfläche Löschen im CommandField in einer DetailsView zuzugreifen. Für die DetailsView erstellen Sie jedoch einen Ereignishandler für das DataBound Ereignis, da DetailsView kein -Ereignis enthält RowDataBound .

Wenn Sie auf die Schaltfläche

Abbildung 4: Klicken auf die Schaltfläche "Löschen" von GridView zeigt ein benutzerdefiniertes Bestätigungsdialogfeld an (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Verwenden von TemplateFields

Einer der Nachteile von CommandField besteht darin, dass auf seine Schaltflächen über die Indizierung zugegriffen werden muss und dass das resultierende Objekt in den entsprechenden Schaltflächentyp (Button, LinkButton oder ImageButton) umgewandelt werden muss. Die Verwendung von "magischen Zahlen" und hartcodierten Typen lädt Probleme ein, die bis zur Laufzeit nicht erkannt werden können. Wenn Sie oder ein anderer Entwickler beispielsweise dem CommandField zu einem späteren Zeitpunkt neue Schaltflächen hinzufügen (z. B. eine Schaltfläche bearbeiten) oder die ButtonType Eigenschaft ändert, wird der vorhandene Code weiterhin ohne Fehler kompiliert, aber der Besuch der Seite kann eine Ausnahme oder unerwartetes Verhalten verursachen, je nachdem, wie Ihr Code geschrieben wurde und welche Änderungen vorgenommen wurden.

Ein alternativer Ansatz besteht darin, die CommandFields von GridView und DetailsView in TemplateFields zu konvertieren. Dadurch wird ein TemplateField mit einem ItemTemplate generiert, das über einen LinkButton (oder Button oder ImageButton) für jede Schaltfläche im CommandField verfügt. Diese Schaltflächeneigenschaften OnClientClick können deklarativ zugewiesen werden, wie wir mit der FormView gesehen haben, oder sie können programmgesteuert im entsprechenden DataBound Ereignishandler mithilfe des folgenden Musters zugegriffen werden:

ButtonType obj = (ButtonType) e.Row.FindControl("controlID");

Wobei controlID der Wert der Eigenschaft der Schaltfläche ist ID . Dieses Muster erfordert zwar weiterhin einen hartcodierten Typ für die Umwandlung, entfällt jedoch die Indizierung, sodass sich das Layout ändern kann, ohne dass es zu einem Laufzeitfehler kommt.

Zusammenfassung

Die JavaScript-Funktion confirm(string) ist eine häufig verwendete Technik zum Steuern des Formularübermittlungsworkflows. Bei Ausführung zeigt die Funktion ein modales, clientseitiges Dialogfeld mit den beiden Schaltflächen OK und Abbrechen an. Wenn der Benutzer auf OK klickt, gibt die confirm(string) Funktion zurück true. Durch Klicken auf Abbrechen wird zurückgegeben false. Diese Funktion kann in Verbindung mit dem Verhalten eines Browsers zum Abbrechen einer Formularübermittlung verwendet werden, wenn ein Ereignishandler während des Übermittlungsprozesses zurückgibt false, um beim Löschen eines Datensatzes ein Bestätigungsmeldungsfeld anzuzeigen.

Die confirm(string) Funktion kann einem clientseitigen onclick Ereignishandler des Button-Websteuerelements über die Eigenschaft s des Steuerelements OnClientClick zugeordnet werden. Wenn Sie mit einer Schaltfläche Löschen in einer Vorlage arbeiten – entweder in einer der FormView-Vorlagen oder in einem TemplateField in der DetailsView oder GridView –, kann diese Eigenschaft entweder deklarativ oder programmgesteuert festgelegt werden, wie in diesem Tutorial gezeigt wurde.

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.