Delen via


Bevestiging aan de clientzijde toevoegen bij het verwijderen (C#)

door Scott Mitchell

PDF downloaden

In de interfaces die we tot nu toe hebben gemaakt, kan een gebruiker per ongeluk gegevens verwijderen door op de knop Verwijderen te klikken wanneer deze bedoeld is om op de knop Bewerken te klikken. In deze zelfstudie voegen we een bevestigingsdialoogvenster aan de clientzijde toe dat wordt weergegeven wanneer op de knop Verwijderen wordt geklikt.

Introductie

In de afgelopen zelfstudies hebben we gezien hoe we onze toepassingsarchitectuur, ObjectDataSource en de besturingselementen voor het gegevensweb kunnen gebruiken om invoeg-, bewerkings- en verwijderingsmogelijkheden te bieden. De verwijderinterfaces die we tot nu toe hebben onderzocht, zijn samengesteld uit een knop Verwijderen die, wanneer erop wordt geklikt, een postback veroorzaakt en de methode ObjectDataSource Delete() aanroept. De Delete() methode roept vervolgens de geconfigureerde methode aan vanuit de bedrijfslogicalaag, die de aanroep naar de Data Access-laag doorgeeft, waarbij de werkelijke DELETE instructie wordt uitgegeven aan de database.

Hoewel deze gebruikersinterface bezoekers in staat stelt records te verwijderen via de besturingselementen GridView, DetailsView of FormView, ontbreekt er een soort bevestiging wanneer de gebruiker op de knop Verwijderen klikt. Als een gebruiker per ongeluk op de knop Verwijderen klikt wanneer hij of zij op Bewerken wilde klikken, wordt de record die hij of zij wilde bijwerken, verwijderd. Om dit te voorkomen, voegen we in deze zelfstudie een bevestigingsvenster aan de clientzijde toe dat wordt weergegeven wanneer op de knop Verwijderen wordt geklikt.

De JavaScript-functie confirm(string) geeft de tekenreeksinvoerparameter weer als de tekst in een modaal dialoogvenster dat is uitgerust met twee knoppen: OK en Annuleren (zie afbeelding 1). De confirm(string) functie retourneert een Booleaanse waarde, afhankelijk van de knop waarop wordt geklikt (trueals de gebruiker op OK klikt en false op Annuleren klikt).

De methode JavaScript confirm(string) geeft een modale Client-Side Messagebox weer

Afbeelding 1: Met de JavaScript-methode confirm(string) wordt een modaal Client-Side Messagebox weergegeven

Als tijdens het indienen van een formulier een waarde van false wordt geretourneerd door een event-handler aan de klantzijde, wordt de inzending van het formulier geannuleerd. Met deze functie kunnen we de event-handler voor de knop Verwijderen aan de clientzijde onclick de waarde van een aanroep laten confirm("Are you sure you want to delete this product?") retourneren. Als de gebruiker op Annuleren klikt, confirm(string) wordt onwaar geretourneerd, waardoor de inzending van het formulier wordt geannuleerd. Zonder terugschrijven wordt het product waarop op de knop Verwijderen is geklikt, niet verwijderd. Als de gebruiker echter op OK klikt in het bevestigingsdialoogvenster, blijft de terugdraaiactie ongewijzigd en wordt het product verwijderd. Raadpleeg de methode JavaScript gebruiken confirm() om formulierinzending te beheren voor meer informatie over deze techniek.

Het toevoegen van het benodigde script aan de clientzijde verschilt enigszins als u sjablonen gebruikt dan wanneer u een CommandField gebruikt. Daarom bekijken we in deze zelfstudie zowel een FormView- als GridView-voorbeeld.

Opmerking

Bij het gebruik van bevestigingstechnieken aan de clientzijde, zoals de technieken die in deze zelfstudie worden besproken, wordt ervan uitgegaan dat uw gebruikers naar browsers gaan die JavaScript ondersteunen en dat JavaScript is ingeschakeld. Als een van deze veronderstellingen niet waar is voor een bepaalde gebruiker, zorgt het klikken op de knop Verwijderen onmiddellijk voor een terugpost (er wordt geen bevestigingsbericht weergegeven).

Stap 1: een FormView maken die ondersteuning biedt voor verwijdering

Voeg eerst een FormView toe aan de ConfirmationOnDelete.aspx pagina in de EditInsertDelete map en bind deze aan een nieuwe ObjectDataSource die de productgegevens terughaalt via de methode van ProductsBLL de GetProducts() klasse. Configureer ook de ObjectDataSource zodat de ProductsBLL methode klasse s DeleteProduct(productID) is toegewezen aan de methode ObjectDataSource Delete() . Zorg ervoor dat de vervolgkeuzelijsten INSERT en UPDATE zijn ingesteld op (Geen). Schakel ten slotte in de SmartTag van FormView het selectievakje voor het inschakelen van Paging aan.

Na deze stappen ziet de nieuwe declaratieve markering van ObjectDataSource er als volgt uit:

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

Zoals in onze eerdere voorbeelden die geen gebruik maken van optimistische gelijktijdigheid, neem de tijd om de eigenschap van ObjectDataSource bij OldValuesParameterFormatString te verwijderen.

Omdat het is gebonden aan een ObjectDataSource-besturingselement dat alleen ondersteuning biedt voor het verwijderen, biedt de FormView s ItemTemplate alleen de knop Verwijderen, zonder de knoppen Nieuw en Bijwerken. De declaratieve markeringen van FormView bevatten echter overbodige EditItemTemplate en InsertItemTemplate, die kunnen worden verwijderd. Neem even de tijd om de ItemTemplate gegevens zo aan te passen dat alleen een subset van de productgegevensvelden wordt weergegeven. Ik heb de mijne geconfigureerd om de naam van het product weer te geven in een <h3> kop boven de leveranciers- en categorienamen (samen met de knop Verwijderen).

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

Met deze wijzigingen hebben we een volledig functionele webpagina waarmee een gebruiker de producten één voor één kan doorlopen, met de mogelijkheid om een product te verwijderen door op de knop Verwijderen te klikken. Afbeelding 2 toont een schermafbeelding van onze voortgang tot nu toe wanneer deze wordt bekeken via een browser.

De FormView toont informatie over één product

Afbeelding 2: De FormView toont informatie over één product (klik om de afbeelding op volledige grootte weer te geven)

Stap 2: de functie confirm(string) aanroepen vanuit de Verwijder-knoppen Client-Side onclick-event

Wanneer formView is gemaakt, is de laatste stap het configureren van de knop Verwijderen, zodat wanneer deze door de bezoeker wordt geklikt, de JavaScript-functie confirm(string) wordt aangeroepen. Het toevoegen van client-side script aan een Button, LinkButton of ImageButton client-side gebeurtenis onclick kan worden gerealiseerd met behulp van de OnClientClick property, die nieuw is sinds ASP.NET 2.0. Omdat we de waarde van de confirm(string) functie willen laten retourneren, stelt u deze eigenschap in op: return confirm('Are you certain that you want to delete this product?');

Na deze wijziging moet de declaratieve syntaxis van Delete LinkButton er ongeveer als volgt uitzien:

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

Dat is alles! Afbeelding 3 toont een schermafbeelding van deze bevestiging in actie. Als u op de knop Verwijderen klikt, wordt het dialoogvenster Bevestigen geopend. Als de gebruiker op Annuleren klikt, wordt de terugdraaiactie geannuleerd en wordt het product niet verwijderd. Als de gebruiker echter op OK klikt, wordt de postback voortgezet en wordt de methode ObjectDataSource Delete() aangeroepen, met als hoogtepunt dat de databaserecord wordt verwijderd.

Opmerking

De tekenreeks die wordt doorgegeven aan de confirm(string) JavaScript-functie, wordt gescheiden door apostrofs (in plaats van aanhalingstekens). In JavaScript kunnen tekenreeksen worden gescheiden met een van beide tekens. We gebruiken hier apostrofs zodat de scheidingstekens voor de tekenreeks die in confirm(string) zijn doorgegeven, geen dubbelzinnigheid veroorzaken met de scheidingstekens die worden gebruikt voor de OnClientClick eigenschapswaarde.

Er wordt nu een bevestiging weergegeven wanneer u op de knop Verwijderen klikt

Afbeelding 3: Er wordt nu een bevestiging weergegeven wanneer u op de knop Verwijderen klikt (klik om de afbeelding op volledige grootte weer te geven)

Stap 3: de eigenschap OnClientClick configureren voor de knop Verwijderen in een CommandField

Wanneer u rechtstreeks in een sjabloon werkt met een knop, LinkButton of ImageButton, kunt u er een bevestigingsdialoogvenster aan koppelen door de OnClientClick-eigenschap zo te configureren dat deze de resultaten van de JavaScript-functie confirm(string) retourneert. CommandField, waarmee een veld met knoppen Verwijderen wordt toegevoegd aan een GridView of DetailsView, heeft OnClientClick echter geen eigenschap die declaratief kan worden ingesteld. In plaats daarvan moeten we programmatisch verwijzen naar de knop Verwijderen in de juiste gebeurtenis-handler van de GridView of DetailsView en vervolgens daar de bijbehorende eigenschap instellen.

Opmerking

Bij het instellen van de eigenschap Delete button s OnClientClick in de juiste DataBound gebeurtenis-handler, hebben we toegang tot de gegevens die zijn gebonden aan de huidige record. Dit betekent dat we het bevestigingsbericht kunnen uitbreiden om details over de specifieke record op te nemen, zoals 'Weet u zeker dat u het Chai-product wilt verwijderen?' Een dergelijke aanpassing is ook mogelijk in sjablonen met behulp van de syntaxis van databinding.

Als u wilt oefenen met het instellen van de OnClientClick eigenschap voor de knop Verwijderen in een CommandField, gaan we een GridView toevoegen aan de pagina. Configureer deze GridView om hetzelfde ObjectDataSource-besturingselement te gebruiken dat door FormView wordt gebruikt. Beperk ook de GridView s BoundFields om alleen de productnaam, categorie en leverancier op te nemen. Schakel ten slotte het selectievakje 'Verwijderen activeren' in van de smarttag van GridView. Hiermee voegt u een CommandField toe aan de verzameling GridView Columns , waarbij de ShowDeleteButton eigenschap is ingesteld op true.

Nadat u deze wijzigingen hebt aangebracht, moet de declaratieve markering van GridView er als volgt uitzien:

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

Het CommandField bevat één Delete LinkButton-exemplaar dat programmatisch kan worden geopend vanuit de gebeurtenis-handler van GridView RowDataBound . Zodra ernaar wordt verwezen, kunnen we de OnClientClick-eigenschap dienovereenkomstig instellen. Maak een gebeurtenis-handler voor de RowDataBound gebeurtenis met behulp van de volgende code:

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("'", @"\'"));
    }
}

Deze eventhandler werkt met gegevensrijen (de rijen die de knop Verwijderen hebben) en begint door programmatisch naar de knop Verwijderen te verwijzen. Gebruik in het algemeen het volgende patroon:

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

ButtonType is het type knop dat wordt gebruikt door CommandField - Button, LinkButton of ImageButton. Het CommandField maakt standaard gebruik van LinkButtons, maar dit kan worden aangepast via CommandField s ButtonType property. De commandFieldIndex is de ordinale index van het CommandField binnen de verzameling GridView Columns , terwijl de controlIndex de index is van de knop Verwijderen in de verzameling CommandField Controls . De waarde controlIndex is afhankelijk van de positie van de knop ten opzichte van andere knoppen in commandfield. Als de enige knop die wordt weergegeven in commandfield bijvoorbeeld de knop Verwijderen is, gebruikt u een index van 0. Als er echter een knop Bewerken is die voorafgaat aan de knop Verwijderen, gebruikt u een index van 2. De reden waarom een index van 2 wordt gebruikt, is omdat twee besturingselementen worden toegevoegd door het CommandField vóór de knop Verwijderen: de knop Bewerken en een LiteralControl die wordt gebruikt om ruimte toe te voegen tussen de knoppen Bewerken en Verwijderen.

Voor ons specifieke voorbeeld gebruikt CommandField LinkButtons en omdat het het meest linkse veld is, heeft het een commandFieldIndex van 0. Omdat er geen andere knoppen zijn, maar de knop Verwijderen in CommandField, gebruiken we een controlIndex van 0.

Nadat u in CommandField naar de knop Verwijderen hebt verwezen, pakken we vervolgens informatie over het product dat is gebonden aan de huidige GridView-rij. Ten slotte stellen we de eigenschap Delete button s OnClientClick in op de juiste JavaScript, die de naam van het product bevat. Omdat de JavaScript-tekenreeks die in de confirm(string) functie wordt doorgegeven, wordt gescheiden met behulp van apostrofs, moeten we ontsnappen aan apostrofs die in de naam van het product worden weergegeven. In het bijzonder worden alle apostrofs in de productnaam met "\'" ge escaped.

Wanneer deze wijzigingen zijn voltooid, en u op de Verwijderknop in de GridView klikt, wordt er een aangepast bevestigingsdialoogvenster weergegeven (zie afbeelding 4). Net als bij het bevestigingsbericht van de FormView, als de gebruiker op Annuleren klikt, wordt de terugpost geannuleerd, waardoor de verwijdering niet kan optreden.

Opmerking

Deze techniek kan ook worden gebruikt om programmatisch toegang te krijgen tot de knop Verwijderen in het CommandField in een DetailsView. Voor de DetailsView maakt u echter een gebeurtenis-handler voor de DataBound gebeurtenis, omdat de DetailsView geen gebeurtenis heeft RowDataBound .

Als u op de knop Verwijderen van GridView klikt, wordt een aangepast bevestigingsdialoogvenster weergegeven

Afbeelding 4: Als u op de knop Rasterweergave verwijderen klikt, wordt een aangepast bevestigingsdialoogvenster weergegeven (klik om de afbeelding op volledige grootte weer te geven)

TemplateFields gebruiken

Een van de nadelen van het CommandField is dat de knoppen moeten worden geopend via indexering en dat het resulterende object moet worden gecast naar het juiste knoptype (Knop, LinkButton of ImageButton). Het gebruik van magic numbers en in code vastgelegde typen nodigt problemen uit die niet kunnen worden gedetecteerd tot de runtime. Als u, of een andere ontwikkelaar, op een bepaald moment in de toekomst nieuwe knoppen toevoegt aan CommandField (zoals een knop Bewerken) of de ButtonType eigenschap wijzigt, wordt de bestaande code nog steeds zonder fouten gecompileerd, maar het bezoeken van de pagina kan een uitzondering of onverwacht gedrag veroorzaken, afhankelijk van hoe uw code is geschreven en welke wijzigingen zijn aangebracht.

Een alternatieve methode is om de CommandFields van GridView en DetailsView te converteren naar TemplateFields. Hiermee wordt een TemplateField gegenereerd met een ItemTemplate dat een LinkButton (of Button of ImageButton) bevat voor elke knop in het CommandField. Deze knoppeneigenschappen OnClientClick kunnen declaratief worden toegewezen, zoals we met de FormView hebben gezien, of kunnen programmatisch worden geopend in de juiste DataBound gebeurtenis-handler met behulp van het volgende patroon:

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

Waar controlID de waarde is van de eigenschap van de knop ID . Hoewel dit patroon nog steeds een in code vastgelegd type voor de cast vereist, wordt de noodzaak voor indexering verwijderd, waardoor de indeling kan worden gewijzigd zonder dat er een runtimefout optreedt.

Samenvatting

De JavaScript-functie confirm(string) is een veelgebruikte techniek voor het beheren van de werkstroom voor het verzenden van formulieren. Wanneer de functie wordt uitgevoerd, wordt een modaal dialoogvenster aan de clientzijde weergegeven met twee knoppen, OK en Annuleren. Als de gebruiker op OK klikt, retourneert de confirm(string) functie true; bij klikken op Annuleren retourneert de false. Deze functionaliteit, in combinatie met het gedrag van een browser om een formulierverzending te annuleren als een gebeurtenis-handler tijdens het indieningsproces terugkeert false, kan worden gebruikt om een bevestigingsberichtvak weer te geven bij het verwijderen van een record.

De confirm(string) functie kan worden gekoppeld aan de client-side gebeurtenis-handler onclick van de Button Web-controle via de eigenschap OnClientClick van het besturingselement. Wanneer u met een knop Verwijderen in een sjabloon werkt ( in een van de sjablonen van FormView of in een TemplateField in DetailsView of GridView), kan deze eigenschap declaratief of programmatisch worden ingesteld, zoals we in deze zelfstudie hebben gezien.

Veel plezier met programmeren!

Over de auteur

Scott Mitchell, auteur van zeven ASP/ASP.NET-boeken en oprichter van 4GuysFromRolla.com, werkt sinds 1998 met Microsoft-webtechnologieën. Scott werkt als onafhankelijk consultant, trainer en schrijver. Zijn laatste boek is Sams Teach Yourself ASP.NET 2.0 in 24 uur. Hij kan worden bereikt op mitchell@4GuysFromRolla.com.