Condividi tramite


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

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 lato client visualizzata quando viene fatto clic sul pulsante Elimina.

Introduzione

Negli ultimi anni sono state illustrate diverse esercitazioni su 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 costituite da un pulsante Delete che, quando è stato fatto clic, provoca un postback e richiama il metodo ObjectDataSource.Delete() Il Delete() metodo richiama quindi il metodo configurato dal livello di logica di business, che propaga la chiamata al livello di accesso ai dati, rilasciando 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, manca qualsiasi tipo di conferma quando l'utente fa clic sul pulsante Elimina. Se un utente fa accidentalmente clic sul pulsante Elimina quando si intende 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 lato client visualizzata quando viene fatto 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 fatto clic su (truese l'utente fa clic su OK e false se fa clic su Annulla).

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

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

Durante l'invio di un modulo, se viene restituito un valore di false da un gestore eventi lato client, l'invio del modulo viene annullato. Usando questa funzionalità, è possibile avere il gestore eventi sul lato onclick client elimina restituisce 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 il cui pulsante Elimina è stato fatto clic su non verrà eliminato. Se, tuttavia, l'utente fa clic su OK nella finestra di dialogo di conferma, il postback continuerà a essere ignorato e il prodotto verrà eliminato. Per altre informazioni su questa tecnica, vedere Uso del metodo JavaScript per controllare l'invio confirm() dei moduli .

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

Nota

L'uso delle tecniche di conferma lato client, come quelle descritte in questa esercitazione, presuppone che gli utenti visitino con browser che supportano JavaScript e che abbiano JavaScript abilitato. Se una di queste ipotesi non è vera per un determinato utente, fare clic sul pulsante Elimina causerà immediatamente un postback (non visualizzando una casella di messaggio di conferma).

Passaggio 1: Creazione di formView che supporta l'eliminazione

Iniziare aggiungendo un FormView alla ConfirmationOnDelete.aspx pagina nella EditInsertDelete cartella, associandolo a un nuovo OggettoDataSource 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 di 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 usavano la concorrenza ottimistica, per cancellare la proprietà ObjectDataSource s OldValuesParameterFormatString .

Poiché è stato associato a un controllo ObjectDataSource che supporta solo l'eliminazione, FormView s ItemTemplate offre solo il pulsante Elimina, senza i pulsanti Nuovo e Aggiorna. Il markup dichiarativo di FormView, tuttavia, include un superfluo EditItemTemplate e InsertItemTemplate, che può essere rimosso. Per personalizzare l'oggetto ItemTemplate in modo da visualizzare solo un subset dei campi dati del prodotto. Ho configurato il mio per visualizzare il nome del prodotto in un'intestazione <h3> sopra i relativi nomi di fornitori e categorie (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 attivare i prodotti uno alla volta, con la possibilità di eliminare un prodotto facendo semplicemente clic sul pulsante Elimina. La figura 2 mostra una schermata dello stato di avanzamento finora quando viene visualizzata 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 full-size)

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

Con la creazione di 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) . È possibile eseguire l'aggiunta di script sul lato client a un evento Button, LinkButton o ImageButton sul lato onclick client tramite l'uso di OnClientClick property, nuovo a 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 aver modificato la sintassi dichiarativa di Delete LinkButton, dovrebbe essere simile a quanto segue:

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

È tutto lì! La figura 3 mostra una schermata di questa conferma in azione. Facendo clic sul pulsante Elimina viene visualizzata la finestra di dialogo 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 di database eliminato.

Nota

La stringa passata alla confirm(string) funzione JavaScript è delimitata con apostrofi (anziché virgolette). In JavaScript le stringhe possono essere delimitate usando entrambi i caratteri. In questo caso vengono usati gli apostrofi in modo che i delimitatori per la stringa passata 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 ora visualizzata una conferma quando si fa clic sul pulsante Elimina (fare clic per visualizzare l'immagine a dimensioni complete)

Passaggio 3: Configurazione della proprietà OnClientClick per il pulsante Delete in un CommandField

Quando si usa un pulsante, linkButton o ImageButton direttamente in un modello, è possibile associare 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 Delete a un oggetto GridView o DetailsView, non dispone di una OnClientClick proprietà che può essere impostata in modo dichiarativo. È invece necessario fare riferimento a livello di codice al pulsante Delete nel gestore eventi appropriato DataBound gridView o DetailsView e quindi impostare la relativa OnClientClick proprietà.

Nota

Quando si imposta la proprietà del OnClientClick pulsante Delete nel gestore eventi appropriato DataBound , è necessario 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 "Sei sicuro di voler eliminare il prodotto Chai?" Tale personalizzazione è anche possibile nei modelli usando la sintassi databinding.

Per praticare l'impostazione della OnClientClick proprietà per i pulsanti Delete in un CommandField, consente di aggiungere gridView alla pagina. Configurare gridView per usare lo stesso controllo ObjectDataSource usato da FormView. Limitare anche GridView s BoundFields solo a includere il nome, la categoria e il fornitore del prodotto. Infine, selezionare la casella di controllo Abilita eliminazione dallo smart tag gridView s. Verrà aggiunto un CommandField all'insieme GridView con Columns la relativa ShowDeleteButton proprietà impostata su true.

Dopo aver apportato queste modifiche, il markup dichiarativo di GridView dovrebbe essere 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 un'unica istanza di Delete LinkButton accessibile a livello di codice dal gestore eventi di GridView.RowDataBound Dopo aver fatto riferimento, è possibile impostare di conseguenza la relativa OnClientClick proprietà. Creare un gestore eventi per l'evento usando il RowDataBound codice seguente:

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

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

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

ButtonType è il tipo di pulsante usato da CommandField - Button, LinkButton o ImageButton. Per impostazione predefinita, CommandField usa LinkButtons, ma è possibile personalizzare tramite CommandField s ButtonType property. Il comandoFieldIndex è l'indice ordinale dell'insieme CommandField all'interno dell'insieme GridViewColumns, mentre il 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, c'è un pulsante Modifica che precede il pulsante Elimina, usare un indice pari a 2. Il motivo per cui viene usato un indice 2 è dovuto al fatto che due controlli vengono aggiunti dal comando CommandField prima del pulsante Elimina: il pulsante Modifica e un valore LetteraleControl usato per aggiungere uno spazio tra i pulsanti Modifica ed Eliminazione.

Per l'esempio specifico, CommandField usa LinkButtons e, essendo il campo più a sinistra, ha un comandoFieldIndex pari a 0. Poiché non sono presenti altri pulsanti, ma il pulsante Elimina in CommandField, viene usato un controlloIndex pari a 0.

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

Con queste modifiche completate, fare clic su un pulsante Elimina nella finestra di dialogo GridView visualizza una finestra di dialogo di conferma personalizzata (vedere La figura 4). Come per la casella di messaggio di conferma da FormView, se l'utente fa clic su Annulla il postback viene annullato, impedendo così che si verifichi l'eliminazione.

Nota

Questa tecnica può essere usata anche per accedere a livello di codice al pulsante Elimina in CommandField in un oggetto DetailsView. Per DetailsView, tuttavia, è necessario creare 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: fare clic sul pulsante Elimina di GridView visualizza una finestra di dialogo di conferma personalizzata (fare clic per visualizzare l'immagine a dimensioni complete)

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:

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

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.