Dela via


Lägga till bekräftelse för Client-Side vid radering (VB)

av Scott Mitchell

Ladda ned PDF

I de gränssnitt som vi har skapat hittills kan en användare oavsiktligt ta bort data genom att klicka på knappen Ta bort när de vill klicka på knappen Redigera. I den här självstudien lägger vi till en bekräftelsedialogruta på klientsidan som visas när knappen Ta bort klickas.

Inledning

Under de senaste självstudierna har vi sett hur vi använder vår programarkitektur, ObjectDataSource och datawebbkontrollerna tillsammans för att tillhandahålla infognings-, redigerings- och borttagningsfunktioner. De borttagningsgränssnitt som vi har undersökt hittills har bestått av en borttagningsknapp som, när det klickas på, orsakar en postback och anropar metoden ObjectDataSource.Delete() Metoden Delete() anropar sedan den konfigurerade metoden från affärslogiklagret, som sprider anropet ned till dataåtkomstlagret och skickar den faktiska DELETE instruktionen till databasen.

Även om det här användargränssnittet gör det möjligt för besökare att ta bort poster via kontrollerna GridView, DetailsView eller FormView, saknar det någon form av bekräftelse när användaren klickar på knappen Ta bort. Om en användare av misstag klickar på knappen Ta bort när de vill klicka på Redigera tas posten som de tänkt uppdatera i stället bort. För att förhindra detta lägger vi i den här handledningen till en bekräftelsedialogruta som visas på klienten när Ta bort-knappen klickas.

JavaScript-funktionen confirm(string) visar sin stränginmatningsparameter som text i en modal dialogruta som är utrustad med två knappar – OK och Avbryt (se bild 1). Funktionen confirm(string) returnerar ett booleskt värde beroende på vilken knapp som klickas (trueom användaren klickar på OK och false klickar på Avbryt).

Metoden JavaScript confirm(string) Visar en modal, Client-Side Messagebox

Bild 1: JavaScript-metoden confirm(string) visar en modal, Client-Side meddelanderuta

Om ett värde false returneras från en händelsehanterare på klientsidan under en formuläröverföring avbryts formuläröverföringen. Med den här funktionen kan vi låta Delete-knappens händelsehanterare på klientsidan onclick returnera värdet av ett anrop till confirm("Are you sure you want to delete this product?"). Om användaren klickar på Avbryt, kommer confirm(string) att returnera false, vilket leder till att formuläret inte skickas. Om det inte sker någon postback, kommer produkten vars borttagningsknapp du klickade inte att tas bort. Om användaren däremot klickar på OK i bekräftelsedialogrutan, fortsätter tillbakaskickningen utan hinder och produkten tas bort. Mer information om den här tekniken finns i Använda JavaScript-metoden confirm() för att styra formuläröverföring .

Att lägga till det nödvändiga skriptet på klientsidan skiljer sig något om du använder mallar än när du använder ett Kommandofält. I den här självstudien tittar vi därför på både ett FormView- och GridView-exempel.

Anmärkning

Med hjälp av bekräftelsetekniker på klientsidan, som de som beskrivs i den här självstudien, förutsätter vi att användarna besöker med webbläsare som stöder JavaScript och att de har JavaScript aktiverat. Om något av dessa antaganden inte är sant för en viss användare, kommer ett återskick att ske direkt när du klickar på knappen Radera (utan att en bekräftelseruta visas).

Steg 1: Skapa en FormView som stöder borttagning

Börja med att lägga till en FormView på ConfirmationOnDelete.aspx sidan i EditInsertDelete mappen och bind den till en ny ObjectDataSource som hämtar produktinformationen ProductsBLL via klassens GetProducts() -metod. Konfigurera även ObjectDataSource så att ProductsBLL klassens DeleteProduct(productID) metod mappas till ObjectDataSources Delete() metod; kontrollera att listrutorna INSERT och UPDATE är inställda på (Ingen). Markera slutligen kryssrutan Aktivera sidsökningsfunktion i smarttaggen FormView.

Efter de här stegen ser den nya ObjectDataSource-deklarativa markeringen ut så här:

<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>

Precis som i våra tidigare exempel som inte använde optimistisk samtidighet, ta en stund på dig att rensa egenskapen hos ObjectDataSource.OldValuesParameterFormatString

Eftersom den har bundits till en ObjectDataSource-kontroll som endast stöder borttagning, erbjuder FormView s ItemTemplate bara knappen Ta bort, utan knapparna Ny och Uppdatera. FormViews deklarativa markering innehåller dock en överflödig EditItemTemplate och InsertItemTemplate, som kan tas bort. Ta en stund att anpassa ItemTemplate så att endast en delmängd av produktdatafälten visas. Jag har konfigurerat min för att visa produktens namn i en <h3> rubrik ovanför dess leverantörs- och kategorinamn (tillsammans med knappen Ta bort).

<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>

Med dessa ändringar har vi en fullt fungerande webbsida som gör det möjligt för en användare att växla igenom produkterna en i taget, med möjlighet att ta bort en produkt genom att helt enkelt klicka på knappen Ta bort. Bild 2 visar en skärmdump av våra framsteg hittills när vi ses via en webbläsare.

FormView visar information om en enskild produkt

Bild 2: Formulärvyn visar information om en enskild produkt (klicka om du vill visa en bild i full storlek)

Steg 2: Anropa funktionen confirm(string) från knapparna för borttagning vid onclick-händelsen Client-Side

När FormView har skapats är det sista steget att konfigurera knappen Ta bort så att JavaScript-funktionen confirm(string) anropas när besökaren klickar på den. Du kan lägga till skript på klientsidan till en knapp-, LinkButton- eller ImageButton-händelse på klientsidan onclick genom att använda OnClientClick property, som är nytt för ASP.NET 2.0. Eftersom vi vill att värdet för confirm(string) funktionen ska returneras anger du bara den här egenskapen till: return confirm('Are you certain that you want to delete this product?');

Efter den här ändringen bör deklarativ syntax för Delete LinkButton se ut ungefär så här:

<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>

Så enkelt är det! Bild 3 visar en skärmbild av den här bekräftelsen i praktiken. När du klickar på knappen Ta bort visas dialogrutan Bekräfta. Om användaren klickar på Avbryt avbryts återanropet och produkten tas inte bort. Om användaren däremot klickar på OK, fortsätter återanropet och metoden ObjectDataSourceDelete() anropas, vilket resulterar i att databasposten tas bort.

Anmärkning

Strängen som skickas till confirm(string) JavaScript-funktionen avgränsas med apostrofer (i stället för citattecken). I JavaScript kan strängar avgränsas med endera tecknet. Vi använder apostrofer här så att avgränsarna för strängen som skickas till confirm(string) inte medför en tvetydighet med avgränsarna som används för egenskapsvärdet OnClientClick .

En bekräftelse visas nu när du klickar på knappen Ta bort

Bild 3: En bekräftelse visas nu när du klickar på knappen Ta bort (Klicka om du vill visa en bild i full storlek)

Steg 3: Konfigurera egenskapen OnClientClick för knappen Ta bort i ett Kommandofält

När du arbetar med en Knapp, LinkButton eller ImageButton direkt i en mall kan en bekräftelsedialogruta associeras med den genom att helt enkelt konfigurera dess OnClientClick egenskap för att returnera resultatet av JavaScript-funktionen confirm(string) . CommandField – som lägger till ett fält med ta bort knappar i en GridView eller DetailsView – har OnClientClick dock ingen egenskap som kan anges deklarativt. I stället måste vi programmässigt referera till knappen Ta bort i GridView eller DetailsViews lämpliga DataBound händelsehanterare och sedan ange dess OnClientClick egenskap där.

Anmärkning

När vi ställer in egenskapen för Ta bort-knappen OnClientClick i lämplig DataBound händelsehanterare har vi åtkomst till data som var kopplade till den aktuella posten. Det innebär att vi kan utöka bekräftelsemeddelandet så att det innehåller information om den specifika posten, till exempel "Vill du ta bort Chai-produkten?" Sådan anpassning är också möjlig i mallar med hjälp av databindningssyntax.

För att öva på att ställa in OnClientClick-egenskapen för Ta bort-knappen/-knapparna i ett Kommandofält lägger vi till en GridView på sidan. Konfigurera den här GridView för att använda samma ObjectDataSource-kontroll som FormView använder. Begränsa även GridViews BoundFields till att endast inkludera produktens namn, kategori och leverantör. Slutligen markerar du kryssrutan Aktivera borttagning från GridViews smarta tagg. Då läggs ett CommandField till i GridView-samlingen Columns med dess ShowDeleteButton egenskap inställd på true.

När du har gjort dessa ändringar bör deklarativ markering för GridView se ut så här:

<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 innehåller en enda Ta bort LinkButton-instans som kan nås programmatiskt från GridView-händelsehanteraren RowDataBound . När vi har refererat till den kan vi ange dess OnClientClick egenskap i enlighet med detta. Skapa en händelsehanterare för RowDataBound händelsen med hjälp av följande kod:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then
        ' reference the Delete LinkButton
        Dim db As LinkButton = CType(e.Row.Cells(0).Controls(0), LinkButton)

        ' Get information about the product bound to the row
        Dim product As Northwind.ProductsRow = _
            CType(CType(e.Row.DataItem, System.Data.DataRowView).Row, _
            Northwind.ProductsRow)

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

Den här händelsehanteraren fungerar med datarader (de som har knappen Ta bort) och börjar med att programmatiskt referera till knappen Ta bort. Använd i allmänhet följande mönster:

Dim obj As ButtonType = _
    CType(e.Row.Cells(commandFieldIndex).Controls(controlIndex), ButtonType)

ButtonType är den typ av knapp som används av CommandField – Button, LinkButton eller ImageButton. Som standard använder CommandField LinkButtons, men detta kan anpassas via CommandField s ButtonType property. CommandFieldIndex är ordningsindexet för CommandField i GridView-samlingenColumns, medan controlIndex är indexet för knappen Ta bort i CommandFields Controls samling. ControlIndex-värdet beror på knappens position i förhållande till andra knappar i Kommandofältet. Om den enda knappen som visas i Kommandofältet till exempel är knappen Ta bort använder du ett index på 0. Om det däremot finns en redigera-knapp som föregår knappen Ta bort använder du ett index på 2. Anledningen till att ett index på 2 används är att två kontroller läggs till av Kommandofältet före knappen Ta bort: knappen Redigera och en LiteralControl som används för att lägga till lite utrymme mellan knapparna Redigera och Ta bort.

I vårt specifika exempel använder CommandField LinkButtons och som det vänstra fältet har commandFieldIndex 0. Eftersom det inte finns några andra knappar än knappen Ta bort i CommandField använder vi ett controlIndex på 0.

När vi har refererat till knappen Ta bort i Kommandofältet hämtar vi sedan information om produkten som är bunden till den aktuella GridView-raden. Slutligen anger vi egenskapen för Ta bort-knappen till OnClientClick lämplig JavaScript, som innehåller produktens namn. Eftersom JavaScript-strängen confirm(string) som skickas till funktionen avgränsas med hjälp av apostrofer måste vi undvika alla apostrofer som visas i produktens namn. I synnerhet undgår apostrofer i produktens namn med "\'".

När ändringarna är klara visas en anpassad bekräftelsedialogruta när du klickar på knappen Ta bort i GridView (se bild 4). Precis som med bekräftelsemeddelanderutan från FormView, om användaren klickar på Avbryt avbryts postbacken, vilket förhindrar att borttagningen sker.

Anmärkning

Den här tekniken kan också användas för att programmatiskt komma åt knappen Ta bort i CommandField i en DetailsView. För DetailsView skapar du dock en händelsehanterare för DataBound händelsen, eftersom DetailsView inte har någon RowDataBound händelse.

Om du klickar på knappen Ta bort i GridView visas en dialogruta för anpassad bekräftelse

Bild 4: Om du klickar på knappen Ta bort i GridView visas en anpassad bekräftelsedialogruta (klicka om du vill visa en bild i full storlek)

Använda TemplateFields

En av nackdelarna med CommandField är att dess knappar måste nås via indexering och att det resulterande objektet måste gjutas till lämplig knapptyp (Knapp, LinkButton eller ImageButton). Användning av "magiska siffror" och hårdkodade typer kan orsaka problem som inte kan upptäckas förrän vid körning. Om du, eller någon annan utvecklare, lägger till nya knappar i CommandField någon gång i framtiden (till exempel en redigera-knapp) eller ändrar ButtonType egenskapen, kompileras den befintliga koden fortfarande utan fel, men om du besöker sidan kan det orsaka ett undantag eller oväntat beteende, beroende på hur koden skrevs och vilka ändringar som gjordes.

En annan metod är att konvertera GridView- och DetailsView-kommandofälten till TemplateFields. Detta genererar ett TemplateField med en ItemTemplate som har en LinkButton (eller Button eller ImageButton) för varje knapp i CommandField. De här knapparnas OnClientClick egenskaper kan tilldelas deklarativt, som vi såg med FormView, eller kan användas programmatiskt i lämplig DataBound händelsehanterare med hjälp av följande mönster:

Dim obj As ButtonType = CType(e.Row.FindControl("controlID"), ButtonType)

Där controlID är värdet för knappegenskapen ID . Även om det här mönstret fortfarande kräver en hårdkodad typ för casten, tar det bort behovet av indexering, vilket gör att layouten kan ändras utan att resultera i ett körningsfel.

Sammanfattning

JavaScript-funktionen confirm(string) är en vanlig teknik för att styra arbetsflödet för formuläröverföring. När den körs visar funktionen en modal dialogruta på klientsidan som innehåller två knappar, OK och Avbryt. Om användaren klickar på OK returnerar funktionen confirm(string)true; om användaren klickar på Avbryt returneras false. Den här funktionen, tillsammans med en webbläsares beteende för att avbryta en formuläröverföring om en händelsehanterare under överföringsprocessen returnerar false, kan användas för att visa en bekräftelsemeddelanderuta när du tar bort en post.

Funktionen confirm(string) kan associeras med en knappwebbkontrolls händelsehanterare på klientsidan onclick via egenskapen control s OnClientClick . När du arbetar med knappen Ta bort i en mall – antingen i någon av FormView-mallarna eller i ett TemplateField i DetailsView eller GridView – kan den här egenskapen anges antingen deklarativt eller programmatiskt, som vi såg i den här självstudien.

Lycka till med programmerandet!

Om författaren

Scott Mitchell, författare till sju ASP/ASP.NET-böcker och grundare av 4GuysFromRolla.com, har arbetat med Microsofts webbtekniker sedan 1998. Scott arbetar som oberoende konsult, tränare och författare. Hans senaste bok är Sams Teach Yourself ASP.NET 2.0 på 24 timmar. Han kan nås på mitchell@4GuysFromRolla.com.