Condividi tramite


Aggiunta di una conferma lato client durante l'eliminazione (VB)

di Scott Mitchell

Scarica il PDF

Nelle interfacce create finora, un utente può eliminare accidentalmente i dati facendo clic sul pulsante Elimina quando si intende fare clic sul pulsante Modifica. In questa esercitazione verrà aggiunta una finestra di dialogo di conferma sul lato client visualizzata quando si fa clic sul pulsante Elimina.

Introduzione

Nelle ultime esercitazioni è stato illustrato come usare l'architettura dell'applicazione, ObjectDataSource e i controlli Web dati in concerto per fornire funzionalità di inserimento, modifica ed eliminazione. Le interfacce di eliminazione esaminate finora sono state composte da un pulsante Elimina che, quando si fa clic, provoca un postback e richiama il metodo ObjectDataSource s Delete() . Il Delete() metodo richiama quindi il metodo configurato dal livello della logica di business, che propaga la chiamata al livello di accesso ai dati, eseguendo l'istruzione effettiva DELETE al database.

Anche se questa interfaccia utente consente ai visitatori di eliminare i record tramite i controlli GridView, DetailsView o FormView, non dispone di alcuna sorta di conferma quando l'utente fa clic sul pulsante Elimina. Se un utente fa clic accidentalmente sul pulsante Elimina quando ha lo scopo di fare clic su Modifica, il record che intendeva aggiornare verrà invece eliminato. Per evitare questo problema, in questa esercitazione verrà aggiunta una finestra di dialogo di conferma sul lato client visualizzata quando si fa clic sul pulsante Elimina.

La funzione JavaScript confirm(string) visualizza il parametro di input stringa come testo all'interno di una finestra di dialogo modale fornita con due pulsanti- OK e Annulla (vedere la figura 1). La confirm(string) funzione restituisce un valore booleano a seconda del pulsante selezionato (true se l'utente fa clic su OK e false se fa clic su Annulla).

Il metodo confirm(string) JavaScript visualizza una casella di messaggio modale Client-Side

Figura 1: Il metodo JavaScript confirm(string) visualizza una finestra di messaggio modale Client-Side

Durante l'invio di un modulo, se viene restituito un valore di false da un gestore eventi sul lato client, l'invio del modulo viene annullato. Usando questa funzionalità, è possibile fare in modo che il gestore eventi lato onclick client del pulsante Delete restituisca il valore di una chiamata a confirm("Are you sure you want to delete this product?"). Se l'utente fa clic su Annulla, confirm(string) restituirà false, causando l'annullamento dell'invio del modulo. Senza postback, il prodotto su cui è stato fatto clic sul pulsante Elimina non verrà eliminato. Se, tuttavia, l'utente fa clic su OK nella finestra di dialogo di conferma, il postback continuerà senza problemi e il prodotto verrà eliminato. Per altre informazioni su questa tecnica, vedere Uso del metodo s confirm() JavaScript per controllare l'invio di moduli.

L'aggiunta dello script lato client necessario è leggermente diversa se si usano modelli rispetto all'uso di un campo CommandField. Di conseguenza, in questa esercitazione verrà esaminato sia un esempio formView che gridView.

Nota

Usando tecniche di conferma lato client, come quelle descritte in questa esercitazione, si presuppone che gli utenti visitino i browser che supportano JavaScript e che abbiano JavaScript abilitato. Se una di queste ipotesi non è vera per un determinato utente, facendo clic sul pulsante Elimina verrà immediatamente generato un postback (non viene visualizzata una finestra di messaggio di conferma).

Passaggio 1: Creazione di un controllo FormView che supporta l'eliminazione

Per iniziare, aggiungere un controllo FormView alla ConfirmationOnDelete.aspx pagina nella EditInsertDelete cartella, associandolo a un nuovo ObjectDataSource che esegue il pull delle informazioni sul prodotto tramite il ProductsBLL metodo della GetProducts() classe . Configurare anche ObjectDataSource in modo che il ProductsBLL metodo della DeleteProduct(productID) classe sia mappato al metodo ObjectDataSource Delete() . Assicurarsi che gli elenchi a discesa INSERT e UPDATE siano impostati su (Nessuno). Infine, selezionare la casella di controllo Abilita paging nello smart tag formView.

Dopo questi passaggi, il nuovo markup dichiarativo di ObjectDataSource sarà simile al seguente:

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

Come negli esempi precedenti che non usano la concorrenza ottimistica, è necessario un po' di tempo per cancellare la proprietà ObjectDataSource.OldValuesParameterFormatString

Poiché è stato associato a un controllo ObjectDataSource che supporta solo l'eliminazione, FormView offre ItemTemplate solo il pulsante Elimina, senza i pulsanti Nuovo e Aggiorna. Il markup dichiarativo di FormView, tuttavia, include un elemento superfluo EditItemTemplate e InsertItemTemplate, che può essere rimosso. Dedicare qualche minuto a personalizzare in ItemTemplate modo che venga visualizzato solo un subset dei campi dati del prodotto. Ho configurato il mio per mostrare il nome del prodotto in un'intestazione <h3> sopra il relativo fornitore e nomi di categoria (insieme al pulsante Elimina).

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

Con queste modifiche, abbiamo una pagina Web completamente funzionale che consente a un utente di passare i prodotti uno alla volta, con la possibilità di eliminare un prodotto semplicemente facendo clic sul pulsante Elimina. La figura 2 mostra uno screenshot dello stato di avanzamento finora visualizzato tramite un browser.

FormView mostra informazioni su un singolo prodotto

Figura 2: FormView mostra informazioni su un singolo prodotto (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 2: Chiamata della funzione confirm(string) dall'evento Delete Buttons Client-Side onclick

Dopo aver creato FormView, il passaggio finale consiste nel configurare il pulsante Elimina in modo che quando viene fatto clic dal visitatore, viene richiamata la funzione JavaScript confirm(string) . L'aggiunta di script sul lato client a un evento sul lato onclick client Button, LinkButton o ImageButton può essere eseguita tramite l'uso di OnClientClick property, che è una novità di ASP.NET 2.0. Poiché si vuole avere il valore della confirm(string) funzione restituita, è sufficiente impostare questa proprietà su: return confirm('Are you certain that you want to delete this product?');

Dopo questa modifica, la sintassi dichiarativa di Delete LinkButton avrà un aspetto simile al seguente:

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

Questo è tutto lì! La figura 3 mostra una schermata di questa conferma in azione. Facendo clic sul pulsante Elimina viene visualizzata la finestra di dialogo di conferma. Se l'utente fa clic su Annulla, il postback viene annullato e il prodotto non viene eliminato. Se, tuttavia, l'utente fa clic su OK, il postback continua e viene richiamato il metodo ObjectDataSource Delete() , che culmina nel record del database da eliminare.

Nota

La stringa passata alla confirm(string) funzione JavaScript è delimitata da apostrofi (anziché tra virgolette). In JavaScript le stringhe possono essere delimitate usando entrambi i caratteri. In questo caso vengono usati apostrofi in modo che i delimitatori per la stringa passata in confirm(string) non introducano un'ambiguità con i delimitatori usati per il valore della OnClientClick proprietà.

Viene ora visualizzata una conferma quando si fa clic sul pulsante Elimina

Figura 3: Viene visualizzata una conferma quando si fa clic sul pulsante Elimina (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 3: Configurazione della proprietà OnClientClick per il pulsante Elimina in un campo di comando

Quando si usa un controllo Button, LinkButton o ImageButton direttamente in un modello, è possibile associarvi una finestra di dialogo di conferma semplicemente configurando la relativa OnClientClick proprietà per restituire i risultati della funzione JavaScript confirm(string) . Tuttavia, commandField, che aggiunge un campo di pulsanti Elimina a un controllo GridView o DetailsView, non dispone di una OnClientClick proprietà che può essere impostata in modo dichiarativo. È invece necessario fare riferimento al pulsante Elimina a livello di codice nel gestore eventi appropriato DataBound di GridView o DetailsView e quindi impostarne la OnClientClick proprietà.

Nota

Quando si imposta la proprietà del pulsante OnClientClick Elimina nel gestore eventi appropriato DataBound , è possibile accedere ai dati associati al record corrente. Ciò significa che è possibile estendere il messaggio di conferma per includere i dettagli relativi al record specifico, ad esempio "Eliminare il prodotto Chai?" Tale personalizzazione è anche possibile nei modelli usando la sintassi databinding.

Per esercitarsi a impostare la OnClientClick proprietà per i pulsanti Elimina in un campo di comando, aggiungere un controllo GridView alla pagina. Configurare questo controllo GridView per l'uso dello stesso controllo ObjectDataSource usato da FormView. Limitare anche i campi BoundField di GridView in modo da includere solo il nome, la categoria e il fornitore del prodotto. Infine, selezionare la casella di controllo Abilita eliminazione dallo smart tag gridView. Verrà aggiunto un oggetto CommandField all'insieme gridView Columns con la relativa ShowDeleteButton proprietà impostata su true.

Dopo aver apportato queste modifiche, il markup dichiarativo di GridView sarà simile al seguente:

<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 contiene una singola istanza di Delete LinkButton a cui è possibile accedere a livello di codice dal gestore eventi di RowDataBound GridView. Una volta fatto riferimento, è possibile impostarne la OnClientClick proprietà di conseguenza. Creare un gestore eventi per l'evento RowDataBound usando il codice seguente:

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

Questo gestore eventi funziona con le righe di dati (quelle che avranno il pulsante Elimina) e inizia facendo riferimento a livello di codice al pulsante Elimina. In generale, usare il modello seguente:

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

ButtonType è il tipo di pulsante utilizzato da CommandField - Button, LinkButton o ImageButton. Per impostazione predefinita, CommandField usa LinkButtons, ma può essere personalizzato tramite commandField s ButtonType property. CommandFieldIndex è l'indice ordinale dell'oggetto CommandField all'interno dell'insieme gridViewColumns, mentre controlIndex è l'indice del pulsante Delete all'interno dell'insieme CommandField.Controls Il valore controlIndex dipende dalla posizione del pulsante rispetto ad altri pulsanti in CommandField. Ad esempio, se l'unico pulsante visualizzato in CommandField è il pulsante Elimina, usare un indice pari a 0. Se, tuttavia, è presente un pulsante Modifica che precede il pulsante Elimina, usare un indice pari a 2. Il motivo per cui viene usato un indice di 2 è dovuto al fatto che due controlli vengono aggiunti da CommandField prima del pulsante Elimina: il pulsante Modifica e un oggetto LiteralControl utilizzato per aggiungere spazio tra i pulsanti Modifica ed Elimina.

Per questo particolare esempio, CommandField usa LinkButtons e, essendo il campo più a sinistra, ha un commandFieldIndex pari a 0. Poiché non sono presenti altri pulsanti, ma il pulsante Elimina in CommandField, viene usato un controlIndex pari a 0.

Dopo aver fatto riferimento al pulsante Elimina in CommandField, verranno ora recuperate informazioni sul prodotto associato alla riga GridView corrente. Infine, impostiamo la proprietà del pulsante OnClientClick Elimina sul codice JavaScript appropriato, che include il nome del prodotto. Poiché la stringa JavaScript passata alla confirm(string) funzione è delimitata usando apostrofi, è necessario eseguire l'escape di eventuali apostrofi che vengono visualizzati all'interno del nome del prodotto. In particolare, qualsiasi apostrofo nel nome del prodotto viene preceduto da "\'".

Al termine di queste modifiche, facendo clic su un pulsante Elimina in GridView viene visualizzata una finestra di dialogo di conferma personalizzata (vedere la figura 4). Come per la finestra di messaggio di conferma da FormView, se l'utente fa clic su Annulla il postback viene annullato, impedendo così l'eliminazione.

Nota

Questa tecnica può essere usata anche per accedere a livello di codice al pulsante Elimina in CommandField in un controllo DetailsView. Per DetailsView, tuttavia, si crea un gestore eventi per l'evento DataBound , poiché DetailsView non ha un RowDataBound evento.

Facendo clic sul pulsante Elimina di GridView viene visualizzata una finestra di dialogo di conferma personalizzata

Figura 4: Facendo clic sul pulsante Elimina di GridView viene visualizzata una finestra di dialogo di conferma personalizzata (fare clic per visualizzare l'immagine a dimensione intera)

Uso di TemplateFields

Uno degli svantaggi del CommandField è che i pulsanti devono essere accessibili tramite l'indicizzazione e che l'oggetto risultante deve essere eseguito il cast al tipo di pulsante appropriato (Button, LinkButton o ImageButton). L'uso di "numeri magici" e tipi hardcoded invita i problemi che non possono essere individuati fino al runtime. Ad esempio, se si o un altro sviluppatore, aggiunge nuovi pulsanti al CommandField in un certo momento (ad esempio un pulsante Modifica) o modifica la ButtonType proprietà, il codice esistente verrà comunque compilato senza errori, ma la visita alla pagina può causare un'eccezione o un comportamento imprevisto, a seconda del modo in cui il codice è stato scritto e quali modifiche sono state apportate.

Un approccio alternativo consiste nel convertire GridView e DetailsView s CommandFields in TemplateFields. In questo modo verrà generato un ModelloField con un ItemTemplate oggetto che ha un LinkButton (o Button o ImageButton) per ogni pulsante nel CommandField. Queste proprietà dei pulsanti OnClientClick possono essere assegnate in modo dichiarativo, come illustrato con FormView o possono essere accessibili a livello di codice nel gestore eventi appropriato DataBound usando il modello seguente:

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

Dove controlID è il valore della proprietà del ID pulsante. Anche se questo modello richiede ancora un tipo hardcoded per il cast, rimuove la necessità di indicizzazione, consentendo al layout di modificare senza generare un errore di runtime.

Riepilogo

La funzione JavaScript confirm(string) è una tecnica comunemente usata per controllare il flusso di lavoro di invio dei moduli. Quando viene eseguita, la funzione visualizza una finestra di dialogo modale sul lato client che include due pulsanti, OK e Annulla. Se l'utente fa clic su OK, la confirm(string) funzione restituisce true. Fare clic su Annulla restituisce false. Questa funzionalità, associata al comportamento di un browser per annullare un invio di modulo se un gestore eventi durante il processo di invio restituisce false, può essere usato per visualizzare una casella di messaggio di conferma durante l'eliminazione di un record.

La confirm(string) funzione può essere associata a un gestore eventi lato onclick client del controllo Web Button tramite la proprietà del controllo.OnClientClick Quando si usa un pulsante Elimina in un modello, ovvero in uno dei modelli di FormView o in un ModelloField in DetailsView o GridView, questa proprietà può essere impostata in modo dichiarativo o a livello di codice, come illustrato in questa esercitazione.

Programmazione felice!

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Microsoft Web dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2,0 in 24 Ore. Può essere raggiunto a mitchell@4GuysFromRolla.com. o tramite il suo blog, che può essere trovato in http://ScottOnWriting.NET.