Freigeben über


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

von Scott Mitchell

PDF herunterladen

In den bisher erstellten Schnittstellen kann ein Benutzer versehentlich Daten löschen, indem er auf die Schaltfläche "Löschen" klickt, wenn er auf die Schaltfläche "Bearbeiten" klicken soll. In diesem Lernprogramm fügen wir ein clientseitiges Bestätigungsdialogfeld hinzu, das angezeigt wird, wenn auf die Schaltfläche "Löschen" geklickt wird.

Einleitung

In den vergangenen Lernprogrammen haben wir erfahren, wie Sie unsere Anwendungsarchitektur, ObjectDataSource und die Datenwebsteuerelemente gemeinsam verwenden, um Funktionen zum Einfügen, Bearbeiten und Löschen bereitzustellen. Die Löschschnittstellen, die wir bisher untersucht haben, bestehen aus einer Schaltfläche "Löschen", die beim Klicken ein Postback verursacht und die ObjectDataSource-Methode Delete() aufruft. Anschließend ruft die Methode Delete() die konfigurierte Methode der Geschäftslogikebene auf, die den Aufruf an die Datenzugriffsschicht weiterleitet und die tatsächliche Anweisung DELETE an die Datenbank weitergibt.

Während diese Benutzeroberfläche es Besuchern ermöglicht, Datensätze über die Steuerelemente GridView, DetailsView oder FormView zu löschen, fehlt es an einer 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 soll, wird der Datensatz, den er aktualisieren soll, stattdessen gelöscht. Um dies zu verhindern, fügen wir in diesem Lernprogramm ein clientseitiges Bestätigungsdialogfeld hinzu, das angezeigt wird, wenn auf die Schaltfläche "Löschen" geklickt wird.

Die JavaScript-Funktion confirm(string) zeigt den 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 auf "Abbrechen" klickt).

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

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

Wenn während einer Formularübermittlung ein Wert von false einem clientseitigen Ereignishandler zurückgegeben wird, wird die Formularübermittlung abgebrochen. Mit dieser Funktion können wir den Ereignishandler der Delete-Schaltfläche auf der Client-Seite so gestalten, dass er den Wert eines Aufrufs von onclick zurückgibt.confirm("Are you sure you want to delete this product?") Wenn der Benutzer auf "Abbrechen" klickt, liefert confirm(string) "false" zurück, wodurch die Formularübermittlung abgebrochen wird. Ohne Postback wird das Produkt, auf dessen Schaltfläche "Löschen" geklickt wurde, nicht gelöscht. Wenn der Benutzer jedoch im Bestätigungsdialogfeld auf "OK" klickt, wird der Postback nicht mehr aktiviert, und das Produkt wird gelöscht. Lesen Sie unter Verwendung von JavaScripts confirm() Methode zur Steuerung der Formularübermittlung, um mehr Informationen zu dieser Technik zu erhalten.

Das Hinzufügen des erforderlichen clientseitigen Skripts unterscheidet sich geringfügig, wenn Vorlagen verwendet werden, gegenüber dem Verwenden eines CommandFields. Daher betrachten wir in diesem Lernprogramm sowohl ein FormView- als auch ein GridView-Beispiel.

Hinweis

Wenn Sie clientseitige Bestätigungstechniken verwenden, wie die in diesem Lernprogramm beschriebenen, wird davon ausgegangen, dass Ihre Benutzer mit Browsern besuchen, die JavaScript unterstützen und JavaScript aktiviert haben. 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 eine Bestätigungsnachricht zu zeigen.

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

Fügen Sie zunächst eine FormView zur ConfirmationOnDelete.aspx Seite im EditInsertDelete Ordner hinzu, binden Sie sie an eine neue ObjectDataSource, die die Produktinformationen über die Methode der ProductsBLL Klasse GetProducts() zurückzieht. Konfigurieren Sie außerdem die ObjectDataSource so, dass die Methode aus der ProductsBLL-Klasse DeleteProduct(productID) der Methode der ObjectDataSource Delete() zugeordnet wird. Stellen Sie sicher, dass die Dropdownlisten für INSERT und UPDATE auf (Keine) eingestellt sind. Aktivieren Sie schließlich 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 OldValuesParameterFormatString zu löschen.

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

<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 durchzuschalten, mit der Möglichkeit, ein Produkt zu löschen, indem er einfach auf die Schaltfläche "Löschen" klickt. Abbildung 2 zeigt einen Screenshot unseres Bisherigen Fortschritts, wenn er über einen Browser angezeigt wird.

FormView zeigt Informationen zu einem einzelnen Produkt an.

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

Schritt 2: Aufrufen der confirm(string)-Funktion beim onclick-Ereignis der Löschschaltflächen Client-Side

Nachdem die FormView erstellt wurde, besteht der letzte Schritt darin, die Schaltfläche "Löschen" so zu konfigurieren, dass beim Klicken durch den Besucher die JavaScript-Funktion confirm(string) aufgerufen wird. Das Hinzufügen eines clientseitigen Skripts zu einem Button-, LinkButton- oder ImageButton-Ereignis auf der Clientseite kann durch die Verwendung des onclick, welches neu in ASP.NET 2.0 ist, durchgeführt werden. Da der Wert der confirm(string) Funktion zurückgegeben werden soll, legen Sie einfach diese Eigenschaft auf: return confirm('Are you certain that you want to delete this product?');

Nach dieser Änderung sollte die deklarative Syntax von Delete LinkButton 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. Durch Klicken auf die Schaltfläche "Löschen" wird das Dialogfeld "Bestätigen" angezeigt. Wenn der Benutzer auf "Abbrechen" klickt, wird der Postback abgebrochen, und das Produkt wird nicht gelöscht. Wenn der Benutzer jedoch auf "OK" klickt, wird der Postback fortgesetzt, und die Methode Delete() des ObjectDataSource wird aufgerufen, was zur Folge hat, 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 beiden Zeichen getrennt werden. Hier verwenden wir Apostrophe, damit die Trennzeichen für die übergebene confirm(string) Zeichenfolge keine Verwirrung mit den Trennzeichen für den OnClientClick Eigenschaftswert verursachen.

Beim Klicken auf die Schaltfläche

Abbildung 3: Eine Bestätigung wird jetzt angezeigt, wenn Sie auf die Schaltfläche "Löschen" klicken (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 einer Schaltfläche, einem LinkButton oder ImageButton direkt in einer Vorlage arbeiten, kann ihm ein Bestätigungsdialogfeld zugeordnet werden, indem sie einfach seine OnClientClick Eigenschaft so konfigurieren, dass die Ergebnisse der JavaScript-Funktion confirm(string) zurückgegeben werden. Das CommandField, das einem GridView- oder DetailsView-Steuerelement ein Feld mit Löschen-Schaltflächen 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 Ereignishandler "GridView" oder "DetailsView" verweisen und dann dessen Eigenschaft dort festlegen OnClientClick .

Hinweis

Zum Festlegen der Eigenschaft der Löschtaste OnClientClick im entsprechenden DataBound Ereignishandler haben wir Zugriff auf die Daten, die an den aktuellen Datensatz gebunden sind. Dies bedeutet, dass wir die Bestätigungsmeldung erweitern können, um Details zum jeweiligen Datensatz einzuschließen, z. B. "Möchten Sie das Chai-Produkt wirklich löschen?" Diese Anpassung ist auch in Vorlagen mithilfe der Datenbindungssyntax möglich.

Wenn Sie die OnClientClick Eigenschaft für die Schaltflächen "Löschen" in einem CommandField festlegen möchten, fügen wir der Seite eine GridView hinzu. Konfigurieren Sie dieses GridView so, dass dasselbe ObjectDataSource-Steuerelement verwendet wird, das von der FormView verwendet wird. Beschränken Sie außerdem die BoundFields von GridView so, dass nur der Name, die Kategorie und der Lieferant des Produkts enthalten sind. Aktivieren Sie schließlich das Kontrollkästchen "Löschen aktivieren" im Smarttag der GridView. Dadurch wird der GridView-Auflistung Columns ein CommandField hinzugefügt, dessen ShowDeleteButton Eigenschaft auf . true festgelegt 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>

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

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 funktioniert mit Datenzeilen (denen, die über die Schaltfläche "Löschen" verfügen) und beginnt, programmgesteuert auf die Schaltfläche "Löschen" zu verweisen. Verwenden Sie im Allgemeinen das folgende Muster:

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

ButtonType ist der Typ der Schaltfläche, die vom CommandField - Button, LinkButton oder ImageButton verwendet wird. Standardmäßig verwendet das CommandField LinkButtons, dies kann jedoch über commandField s ButtonType propertyangepasst werden. " commandFieldIndex " ist der Ordinalindex des CommandField innerhalb der GridView-Auflistung Columns , während " controlIndex " der Index der Schaltfläche "Delete" innerhalb der CommandField-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 einen Index von 0. Wenn jedoch eine Schaltfläche "Bearbeiten" vorhanden ist, die der Schaltfläche "Löschen" vorangestellt ist, verwenden Sie einen Index von 2. Der Grund für die Verwendung eines Indexes von 2 ist, dass zwei Steuerelemente vom CommandField vor der Schaltfläche "Löschen" hinzugefügt werden: die Schaltfläche "Bearbeiten" und ein "LiteralControl", das zum Hinzufügen von Leerzeichen zwischen den Schaltflächen "Bearbeiten" und "Löschen" verwendet wird.

In unserem speziellen Beispiel verwendet CommandField LinkButtons und hat als linksstes Feld einen CommandFieldIndex von 0. Da es keine anderen Schaltflächen, sondern die Schaltfläche "Löschen" im CommandField gibt, verwenden wir einen controlIndex von 0.

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

Wenn diese Änderungen abgeschlossen sind, wird durch Klicken auf eine Schaltfläche "Löschen" in der GridView ein angepasstes Bestätigungsdialogfeld angezeigt (siehe Abbildung 4). Wie bei dem Bestätigungsmeldungsfeld aus der FormView, wenn der Benutzer auf "Abbrechen" klickt, wird der Postback abgebrochen, wodurch verhindert wird, dass der Löschvorgang auftritt.

Hinweis

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

Wenn Sie auf die Schaltfläche

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

Verwenden von TemplateFields

Einer der Nachteile des CommandField besteht darin, dass auf die Schaltflächen über die Indizierung zugegriffen werden muss und dass das resultierende Objekt in den entsprechenden Schaltflächentyp (Button, LinkButton oder ImageButton) umgeformt werden muss. Die Verwendung von "magischen Zahlen" und hart codierten Typen führt zu Problemen, die erst zur Laufzeit entdeckt werden können. Wenn Sie oder ein anderer Entwickler beispielsweise zu einem bestimmten Zeitpunkt neue Schaltflächen zum CommandField hinzufügen (z. B. eine Bearbeitungsschaltfläche) oder die Eigenschaft ändert, wird der ButtonType vorhandene Code weiterhin ohne Fehler kompiliert, der Besuch der Seite kann jedoch eine Ausnahme oder unerwartetes Verhalten verursachen, je nachdem, wie Der Code geschrieben wurde und welche Änderungen vorgenommen wurden.

Eine alternative Methode besteht darin, die CommandFields von GridView und DetailsView in TemplateFields zu konvertieren. Dadurch wird ein TemplateField mit einem ItemTemplate erstellt, das für jede Schaltfläche im CommandField einen LinkButton (oder Button oder ImageButton) enthält. Diese Schaltflächeneigenschaften OnClientClick können, wie wir mit der FormView gesehen haben, deklarativ zugewiesen oder mit dem folgenden Muster programmgesteuert in dem entsprechenden DataBound Ereignishandler zugegriffen werden.

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

Dabei ist controlID der Wert der Eigenschaft der Schaltfläche ID . Obwohl für dieses Muster weiterhin ein fest codierter Typ für die Umwandlung erforderlich ist, entfällt die Notwendigkeit der Indizierung, sodass sich das Layout ändern kann, ohne dass ein Laufzeitfehler auftritt.

Zusammenfassung

Die JavaScript-Funktion confirm(string) ist eine häufig verwendete Technik zum Steuern des Formularübermittlungsworkflows. Wenn die Funktion ausgeführt wird, zeigt die Funktion ein modales, clientseitiges Dialogfeld mit zwei Schaltflächen, OK und Abbrechen an. Wenn der Benutzer auf "OK" klickt, gibt die confirm(string)-Funktion true zurück; durch Klicken auf "Abbrechen" gibt sie false zurück. Diese Funktionalität, zusammen mit dem Verhalten eines Browsers, eine Formularübermittlung abzubrechen, wenn ein Ereignishandler während des Übermittlungsprozesses false zurückgibt, kann verwendet werden, um beim Löschen eines Datensatzes ein Bestätigungsdialogfeld anzuzeigen.

Die Funktion confirm(string) kann durch die onclick-Eigenschaft einem clientseitigen OnClientClick-Ereignishandler eines Schaltflächen-Websteuerelements 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 wir in diesem Lernprogramm gesehen haben.

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.