Ajout d’une confirmation côté client lors de la suppression (C#)
par Scott Mitchell
Dans les interfaces que nous avons créées jusqu’à présent, un utilisateur peut accidentellement supprimer des données en cliquant sur le bouton Supprimer lorsqu’il devait cliquer sur le bouton Modifier. Dans ce tutoriel, nous allons ajouter une boîte de dialogue de confirmation côté client qui s’affiche lorsque l’utilisateur clique sur le bouton Supprimer.
Introduction
Au cours des derniers tutoriels, nous avons vu comment utiliser notre architecture d’application, ObjectDataSource et les contrôles web de données de concert pour fournir des fonctionnalités d’insertion, de modification et de suppression. Les interfaces de suppression que nous avons examinées jusqu’à présent sont composées d’un bouton Supprimer qui, lorsqu’on y clique, provoque une publication et appelle la méthode ObjectDataSource Delete()
. La Delete()
méthode appelle ensuite la méthode configurée à partir de la couche logique métier, qui propage l’appel à la couche d’accès aux données, en émettant l’instruction réelle DELETE
à la base de données.
Bien que cette interface utilisateur permette aux visiteurs de supprimer des enregistrements via les contrôles GridView, DetailsView ou FormView, elle n’a pas de confirmation lorsque l’utilisateur clique sur le bouton Supprimer. Si un utilisateur clique accidentellement sur le bouton Supprimer alors qu’il voulait cliquer sur Modifier, l’enregistrement qu’il voulait mettre à jour est à la place supprimé. Pour éviter cela, dans ce tutoriel, nous allons ajouter une boîte de dialogue de confirmation côté client qui s’affiche lorsque l’utilisateur clique sur le bouton Supprimer.
La fonction JavaScript confirm(string)
affiche son paramètre d’entrée de chaîne en tant que texte à l’intérieur d’une boîte de dialogue modale dotée de deux boutons : OK et Annuler (voir la figure 1). La confirm(string)
fonction retourne une valeur booléenne en fonction du bouton sur lequel l’utilisateur clique (true
si l’utilisateur clique sur OK et false
s’il clique sur Annuler).
Figure 1 : La méthode JavaScript confirm(string)
affiche une boîte de message modale Client-Side
Lors d’une soumission de formulaire, si une valeur de false
est retournée à partir d’un gestionnaire d’événements côté client, la soumission du formulaire est annulée. À l’aide de cette fonctionnalité, nous pouvons faire en sorte que le gestionnaire d’événements côté onclick
client du bouton Supprimer retourne la valeur d’un appel à confirm("Are you sure you want to delete this product?")
. Si l’utilisateur clique sur Annuler, confirm(string)
retourne false, ce qui entraîne l’annulation de l’envoi du formulaire. Sans publication, le produit sur lequel l’utilisateur a cliqué sur le bouton Supprimer ne sera pas supprimé. Toutefois, si l’utilisateur clique sur OK dans la boîte de dialogue de confirmation, la publication continue sans relâche et le produit est supprimé. Pour plus d’informations sur cette technique, consultez Utilisation de la confirm()
méthode JavaScript pour contrôler l’envoi de formulaires.
L’ajout du script côté client nécessaire diffère légèrement si vous utilisez des modèles par rapport à l’utilisation d’un champ de commande. Par conséquent, dans ce tutoriel, nous allons examiner à la fois un exemple FormView et GridView.
Notes
L’utilisation de techniques de confirmation côté client, comme celles décrites dans ce tutoriel, suppose que vos utilisateurs visitent des navigateurs qui prennent en charge JavaScript et que JavaScript est activé. Si l’une de ces hypothèses n’est pas vraie pour un utilisateur particulier, le fait de cliquer sur le bouton Supprimer entraîne immédiatement une publication (n’affichant pas de boîte de message de confirmation).
Étape 1 : Création d’un FormView qui prend en charge la suppression
Commencez par ajouter un Objet FormView à la ConfirmationOnDelete.aspx
page dans le dossier, en le EditInsertDelete
liant à un nouvel ObjetDataSource qui extrait les informations de produit via la ProductsBLL
méthode class s GetProducts()
. Configurez également ObjectDataSource de sorte que la méthode de la ProductsBLL
classe soit DeleteProduct(productID)
mappée à la méthode ObjectDataSource Delete()
; vérifiez que les listes déroulantes INSERT et UPDATE sont définies sur (Aucun). Enfin, case activée la case Activer la pagination dans la balise active de FormView.
Après ces étapes, le nouveau balisage déclaratif d’ObjectDataSource se présente comme suit :
<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>
Comme dans nos exemples précédents qui n’utilisaient pas l’accès concurrentiel optimiste, prenez un moment pour effacer la propriété de OldValuesParameterFormatString
ObjectDataSource.
Étant donné qu’il a été lié à un contrôle ObjectDataSource qui prend uniquement en charge la suppression, formView offre ItemTemplate
uniquement le bouton Supprimer, sans les boutons Nouveau et Mettre à jour. Toutefois, le balisage déclaratif de FormView inclut un superflu EditItemTemplate
et InsertItemTemplate
, qui peut être supprimé. Prenez un moment pour personnaliser le ItemTemplate
afin d’afficher uniquement un sous-ensemble des champs de données de produit. J’ai configuré le mien pour afficher le nom du produit dans un <h3>
en-tête au-dessus de ses noms de fournisseur et de catégorie (avec le bouton Supprimer).
<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>
Avec ces modifications, nous disposons d’une page web entièrement fonctionnelle qui permet à un utilisateur de basculer entre les produits un par un, avec la possibilité de supprimer un produit en cliquant simplement sur le bouton Supprimer. La figure 2 montre une capture d’écran de notre progression jusqu’à présent lorsqu’elle est consultée via un navigateur.
Figure 2 : FormView affiche des informations sur un seul produit (cliquer pour afficher une image en taille réelle)
Étape 2 : Appel de la fonction confirm(string) à partir de l’événement Delete Buttons Client-Side onclick
Une fois formView créé, la dernière étape consiste à configurer le bouton Supprimer de telle sorte que lorsque le visiteur clique dessus, la fonction JavaScript confirm(string)
soit appelée. L’ajout d’un script côté client à un événement côté onclick
client Button, LinkButton ou ImageButton peut être effectué à l’aide de OnClientClick property
, qui est nouveau dans ASP.NET 2.0. Étant donné que nous voulons que la valeur de la confirm(string)
fonction soit retournée, définissez simplement cette propriété sur : return confirm('Are you certain that you want to delete this product?');
Après cette modification, la syntaxe déclarative de Delete LinkButton doit ressembler à ceci :
<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>
C’est tout ce qu’il y a à faire ! La figure 3 montre une capture d’écran de cette confirmation en action. Si vous cliquez sur le bouton Supprimer, la boîte de dialogue Confirmer s’affiche. Si l’utilisateur clique sur Annuler, la publication est annulée et le produit n’est pas supprimé. Toutefois, si l’utilisateur clique sur OK, la publication continue et la méthode ObjectDataSource Delete()
est appelée, ce qui aboutit à la suppression de l’enregistrement de base de données.
Notes
La chaîne passée dans la confirm(string)
fonction JavaScript est délimitée par des apostrophes (plutôt que des guillemets). En JavaScript, les chaînes peuvent être délimitées à l’aide de l’un ou l’autre caractère. Nous utilisons ici des apostrophes afin que les délimiteurs de la chaîne passée n’introduisent confirm(string)
pas d’ambiguïté avec les délimiteurs utilisés pour la valeur de propriété OnClientClick
.
Figure 3 : Une confirmation s’affiche maintenant lorsque vous cliquez sur le bouton Supprimer (cliquez pour afficher l’image en taille réelle)
Étape 3 : Configuration de la propriété OnClientClick pour le bouton Supprimer dans un champ de commandes
Lorsque vous utilisez un Button, LinkButton ou ImageButton directement dans un modèle, une boîte de dialogue de confirmation peut y être associée en configurant simplement sa OnClientClick
propriété pour retourner les résultats de la fonction JavaScript confirm(string)
. Toutefois, le Champ de commande , qui ajoute un champ de boutons Supprimer à un Objet GridView ou DetailsView, n’a pas de OnClientClick
propriété qui peut être définie de manière déclarative. Au lieu de cela, nous devons référencer par programmation le bouton Supprimer dans le gestionnaire d’événements approprié DataBound
de GridView ou DetailsView, puis y définir sa OnClientClick
propriété.
Notes
Lorsque vous définissez la propriété du OnClientClick
bouton Supprimer dans le gestionnaire d’événements approprié DataBound
, nous avons accès aux données liées à l’enregistrement actif. Cela signifie que nous pouvons étendre le message de confirmation pour inclure des détails sur l’enregistrement particulier, par exemple, « Êtes-vous sûr de vouloir supprimer le produit Chai ? » Cette personnalisation est également possible dans les modèles à l’aide de la syntaxe de liaison de données.
Pour vous entraîner à définir la OnClientClick
propriété pour le ou les boutons Supprimer dans un Champ de commande, nous allons ajouter un GridView à la page. Configurez ce GridView pour utiliser le même contrôle ObjectDataSource que celui utilisé par FormView. Limitez également les limites de GridView pour inclure uniquement le nom du produit, la catégorie et le fournisseur. Enfin, case activée la case Activer la suppression de la balise active de GridView. Cela ajoute un CommandField à la collection GridView Columns
avec sa ShowDeleteButton
propriété définie sur true
.
Après avoir apporté ces modifications, votre balisage déclaratif gridView doit ressembler à ce qui suit :
<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 contient un seul instance Delete LinkButton accessible par programmation à partir du gestionnaire d’événements GridViewRowDataBound
. Une fois référencé, nous pouvons définir sa OnClientClick
propriété en conséquence. Créez un gestionnaire d’événements pour l’événement à l’aide RowDataBound
du code suivant :
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("'", @"\'"));
}
}
Ce gestionnaire d’événements fonctionne avec les lignes de données (celles qui auront le bouton Supprimer) et commence par référencer par programmation le bouton Supprimer. En général, utilisez le modèle suivant :
ButtonType obj = (ButtonType) e.Row.Cells[commandFieldIndex].Controls[controlIndex];
ButtonType est le type de bouton utilisé par l’objet CommandField - Button, LinkButton ou ImageButton. Par défaut, le Champ de commande utilise LinkButtons, mais il peut être personnalisé via commandField s ButtonType property
. CommandFieldIndex est l’index ordinal de CommandField dans la collection gridViewColumns
, tandis que le controlIndex est l’index du bouton Supprimer dans la collection CommandField.Controls
La valeur controlIndex dépend de la position du bouton par rapport aux autres boutons dans le Champ de commande. Par exemple, si le seul bouton affiché dans le champ de commandes est le bouton Supprimer, utilisez un index de 0. Si, toutefois, un bouton Modifier précède le bouton Supprimer, utilisez un index de 2. La raison pour laquelle un index de 2 est utilisé est dû au fait que deux contrôles sont ajoutés par le Champ de commande avant le bouton Supprimer : le bouton Modifier et un LiteralControl qui est utilisé pour ajouter de l’espace entre les boutons Modifier et Supprimer.
Pour notre exemple particulier, commandField utilise LinkButtons et, étant le champ le plus à gauche, a un commandFieldIndex de 0. Étant donné qu’il n’existe pas d’autres boutons que le bouton Supprimer dans commandField, nous utilisons un controlIndex de 0.
Après avoir référencé le bouton Supprimer dans le Champ de commande, nous récupérons ensuite des informations sur le produit lié à la ligne GridView actuelle. Enfin, nous définissons la propriété Delete button s OnClientClick
sur le Code JavaScript approprié, qui inclut le nom du produit. Étant donné que la chaîne JavaScript passée dans la confirm(string)
fonction est délimitée à l’aide d’apostrophes, nous devons échapper toutes les apostrophes qui apparaissent dans le nom du produit. En particulier, toutes les apostrophes dans le nom du produit sont placées dans une séquence d’échappement avec «\'
».
Une fois ces modifications terminées, le fait de cliquer sur un bouton Supprimer dans GridView affiche une boîte de dialogue de confirmation personnalisée (voir la figure 4). Comme avec la boîte de message de confirmation de FormView, si l’utilisateur clique sur Annuler, la publication est annulée, empêchant ainsi la suppression.
Notes
Cette technique peut également être utilisée pour accéder par programmation au bouton Supprimer dans le Champ de commande dans un DetailsView. Toutefois, pour DetailsView, vous devez créer un gestionnaire d’événements pour l’événement DataBound
, car detailsView n’a pas d’événement RowDataBound
.
Figure 4 : Cliquer sur le bouton Supprimer de GridView affiche une boîte de dialogue de confirmation personnalisée (cliquez pour afficher l’image en taille réelle)
Utilisation de TemplateFields
L’un des inconvénients de CommandField est que ses boutons doivent être accessibles via l’indexation et que l’objet résultant doit être casté vers le type de bouton approprié (Button, LinkButton ou ImageButton). L’utilisation de « nombres magiques » et de types codés en dur invite à des problèmes qui ne peuvent pas être découverts avant l’exécution. Par exemple, si vous, ou un autre développeur, ajoutez de nouveaux boutons au Champ de commande à un moment donné (par exemple, un bouton Modifier) ou modifiez la ButtonType
propriété, le code existant sera toujours compilé sans erreur, mais la visite de la page peut entraîner une exception ou un comportement inattendu, selon la façon dont votre code a été écrit et les modifications qui ont été apportées.
Une autre approche consiste à convertir les Champs de commande GridView et DetailsView en TemplateFields. Cela génère un TemplateField avec un ItemTemplate
qui a un LinkButton (ou Button ou ImageButton) pour chaque bouton dans le Champ de commandes. Ces propriétés de boutons peuvent être attribuées OnClientClick
de manière déclarative, comme nous l’avons vu avec FormView, ou sont accessibles par programmation dans le gestionnaire d’événements approprié DataBound
à l’aide du modèle suivant :
ButtonType obj = (ButtonType) e.Row.FindControl("controlID");
Où controlID est la valeur de la propriété s du ID
bouton. Bien que ce modèle nécessite toujours un type codé en dur pour le cast, il supprime la nécessité d’indexation, ce qui permet à la disposition de changer sans entraîner d’erreur d’exécution.
Résumé
La fonction JavaScript confirm(string)
est une technique couramment utilisée pour contrôler le flux de travail de soumission de formulaire. Lorsqu’elle est exécutée, la fonction affiche une boîte de dialogue modale côté client qui comprend deux boutons, OK et Annuler. Si l’utilisateur clique sur OK, la confirm(string)
fonction retourne true
; cliquer sur Annuler renvoie false
. Cette fonctionnalité, associée à un comportement du navigateur pour annuler l’envoi d’un formulaire si un gestionnaire d’événements pendant le processus de soumission retourne false
, peut être utilisée pour afficher une boîte de message de confirmation lors de la suppression d’un enregistrement.
La confirm(string)
fonction peut être associée à un gestionnaire d’événements côté onclick
client du contrôle Button Web via la propriété s du OnClientClick
contrôle. Lorsque vous utilisez un bouton Supprimer dans un modèle ( dans l’un des modèles De FormView ou dans un TemplateField dans DetailsView ou GridView ), cette propriété peut être définie de manière déclarative ou programmatique, comme nous l’avons vu dans ce tutoriel.
Bonne programmation !
À propos de l’auteur
Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille comme consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 in 24 Heures. Il est accessible à l’adressemitchell@4GuysFromRolla.com . ou via son blog, qui peut être trouvé à l’adresse http://ScottOnWriting.NET.