Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
par Scott Mitchell
Dans les interfaces que nous avons créées jusqu’à présent, un utilisateur peut supprimer accidentellement des données en cliquant sur le bouton Supprimer lorsqu’il voulait 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 le bouton Supprimer est cliqué.
Présentation
Au cours des derniers didacticiels, nous avons vu comment utiliser notre architecture d’application, ObjectDataSource et les contrôles Web de données en 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 ont été composées d’un bouton Supprimer qui, lorsqu'on clique dessus, 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 permet aux visiteurs de supprimer des enregistrements via les contrôles GridView, DetailsView ou FormView, il n’existe aucune sorte de confirmation lorsque l’utilisateur clique sur le bouton Supprimer. Si un utilisateur clique accidentellement sur le bouton Supprimer lorsqu’il veut cliquer sur Modifier, l’enregistrement qu’il a destiné à mettre à jour sera supprimé à la place. Pour éviter cela, dans ce tutoriel, nous allons ajouter une boîte de dialogue de confirmation côté client qui s’affiche lorsque le bouton Supprimer est cliqué.
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 qui est équipé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 le bouton est cliqué (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
Pendant une soumission de formulaire, si une valeur est false
retournée par un gestionnaire d’événements côté client, la soumission de formulaire est annulée. En utilisant cette fonctionnalité, nous pouvons faire en sorte que le gestionnaire d'événements côté onclick
client du bouton Supprimer renvoie 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 la soumission du formulaire. Sans retour de publication, le produit pour lequel le bouton Supprimer a été cliqué ne sera pas supprimé. Si, toutefois, l’utilisateur clique sur OK dans la boîte de dialogue de confirmation, la publication continue sans problème et le produit est supprimé. Pour plus d’informations sur cette technique, consultez l’utilisation de la méthode JavaScript pour confirm()
contrôler la soumission de formulaire .
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 CommandField. Par conséquent, dans ce tutoriel, nous allons examiner un exemple FormView et GridView.
Remarque
L’utilisation de techniques de confirmation côté client, comme celles décrites dans ce didacticiel, suppose que vos utilisateurs visitent des navigateurs qui prennent en charge JavaScript et qu’ils ont activé JavaScript. Si l'une ou l'autre de ces hypothèses n'est pas vraie pour un utilisateur particulier, en cliquant sur le bouton Supprimer, cela entraînera immédiatement un postback (sans afficher de boîte de dialogue de confirmation).
Étape 1 : Création d’un FormView qui prend en charge la suppression
Commencez par ajouter un FormView à la page ConfirmationOnDelete.aspx
dans le dossier EditInsertDelete
, en le liant à un nouvel ObjectDataSource qui extrait les informations du produit via la méthode de la classe ProductsBLL
GetProducts()
. Configurez également ObjectDataSource afin que la méthode ProductsBLL
de la classe DeleteProduct(productID)
soit mappée à la méthode Delete()
de ObjectDataSource ; vérifiez que les listes déroulantes INSERT et UPDATE sont définies sur (Aucun). Enfin, cochez l'option Activer la pagination dans le smart tag de FormView.
Après ces étapes, le nouveau balisage déclaratif 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 passés qui n’utilisaient pas la concurrence optimiste, prenez un moment pour effacer la propriété ObjectDataSource OldValuesParameterFormatString
.
Étant donné qu’il a été lié à un contrôle ObjectDataSource qui prend uniquement en charge la suppression, formView s ItemTemplate
offre uniquement le bouton Supprimer, sans les boutons Nouveau et Mettre à jour. Toutefois, le balisage déclaratif de FormView inclut un élément superflu EditItemTemplate
et InsertItemTemplate
, qui peut être supprimé. Prenez un moment pour personnaliser ItemTemplate
pour qu’il affiche uniquement un sous-ensemble des champs de données du produit. J'ai configuré la mienne pour afficher le nom du produit dans un <h3>
en-tête au-dessus des noms de son fournisseur et de sa catégorie (ainsi que 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 (cliquez pour afficher l’image de taille complète)
Étape 2 : Appel de la fonction confirm(string) à partir de l'événement onclick des boutons Supprimer Client-Side
Une fois que le FormView est créé, la dernière étape consiste à configurer le bouton Supprimer de sorte que lorsque le visiteur clique dessus, la fonction JavaScript confirm(string)
est appelée. L’ajout d’un script côté client à l’événement côté onclick
client d’un Button, LinkButton ou ImageButton peut être effectué à l’aide de l’élément OnClientClick property
, qui est nouveau dans ASP.NET 2.0. Comme nous voulons avoir la valeur de la confirm(string)
fonction 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 à ça ! La figure 3 montre une capture d’écran de cette confirmation en action. Cliquer sur le bouton Supprimer affiche la boîte de dialogue confirmer. Si l’utilisateur clique sur Annuler, la publication est annulée et le produit n’est pas supprimé. Si, toutefois, l’utilisateur clique sur OK, le retour continue et la méthode Delete()
de ObjectDataSource est appelée, ce qui aboutit à la suppression de l’enregistrement de la base de données.
Remarque
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 dans confirm(string)
n'introduisent 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 de taille complète)
Étape 3 : Configuration de la propriété OnClientClick pour le bouton Supprimer dans un Champ de commande
Lorsque vous utilisez un bouton, LinkButton ou ImageButton directement dans un modèle, une boîte de dialogue de confirmation peut être associée en configurant simplement sa OnClientClick
propriété pour renvoyer les résultats de la fonction JavaScript confirm(string)
. Toutefois, commandField , qui ajoute un champ de boutons Delete à un 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 définir sa OnClientClick
propriété là-bas.
Remarque
Lorsque vous définissez la propriété du bouton Supprimer dans le gestionnaire d’événements OnClientClick
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, comme « Ê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 Delete 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 s BoundFields pour inclure uniquement le nom, la catégorie et le fournisseur du produit. Enfin, cochez la case Activer la suppression à partir de la balise intelligente de GridView. Cela ajoute un Champ de commande à la collection GridView Columns
avec sa ShowDeleteButton
propriété définie sur true
.
Après avoir apporté ces modifications, le balisage déclaratif de 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 une seule instance Delete LinkButton accessible par programme à partir du gestionnaire d’événements RowDataBound
GridView. 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 RowDataBound
en utilisant le 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 des 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 CommandField - Button, LinkButton ou ImageButton. Par défaut, CommandField utilise LinkButtons, mais cela peut être personnalisé via CommandField s ButtonType property
.
CommandFieldIndex est l’index ordinal de l’objet CommandField dans la collection GridViewColumns
, tandis que le controlIndex est l’index du bouton Delete dans la collection CommandFieldControls
. La valeur controlIndex dépend de la position du bouton par rapport à d’autres boutons dans CommandField. Par exemple, si le seul bouton affiché dans Le Champ de commande est le bouton Supprimer, utilisez un index de 0. Si, toutefois, il existe un bouton Modifier qui précède le bouton Supprimer, utilisez un index de 2. La raison pour laquelle un index de 2 est utilisé est parce que deux contrôles sont ajoutés par le Champ de commande avant le bouton Supprimer : le bouton Modifier et un LiteralControl utilisé pour ajouter un 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’autre bouton à part le bouton Supprimer dans le CommandField, nous utilisons un controlIndex de 0.
Après avoir référencé le bouton Supprimer dans CommandField, nous récupérons ensuite des informations sur le produit lié à la ligne GridView actuelle. Enfin, nous définissons la propriété du OnClientClick
bouton Supprimer 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 échappées avec « \'
».
Une fois ces modifications terminées, cliquez sur un bouton Supprimer dans GridView pour afficher 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, ce qui empêche la suppression de se produire.
Remarque
Cette technique peut également être utilisée pour accéder par programmation au bouton Supprimer dans commandField dans un DetailsView. Pour DetailsView, toutefois, vous créez 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 de taille complète)
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 converti en 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 jusqu’à l’exécution. Par exemple, si vous ou un autre développeur ajoutez de nouveaux boutons à CommandField à un moment donné (par exemple, un bouton Modifier) ou modifiez la ButtonType
propriété, le code existant se compile toujours sans erreur, mais la page peut provoquer une exception ou un comportement inattendu, selon la façon dont votre code a été écrit et les modifications apportées.
Une autre approche consiste à convertir les champs CommandFields gridView et DetailsView en TemplateFields. Cela génère un TemplateField avec un ItemTemplate
qui contient un LinkButton (ou Button ou ImageButton) pour chaque bouton dans le CommandField. 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é de ID
bouton. Bien que ce modèle nécessite toujours un type codé en dur pour le cast, il supprime la nécessité de l’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 Cancel. Si l’utilisateur clique sur OK, la confirm(string)
fonction retourne true
; en cliquant sur Annuler.false
Cette fonctionnalité, couplée au comportement d’un navigateur pour annuler une soumission de formulaire si un gestionnaire d’événements pendant le processus de soumission retourne false
, peut être utilisé pour afficher une boîte de message de confirmation lors de la suppression d’un enregistrement.
La fonction confirm(string)
peut être associée à un gestionnaire d'événements onclick
côté client du contrôle Web Button via la propriété OnClientClick
du contrôle. Lorsque vous utilisez un bouton Supprimer dans un modèle ( dans l’un des modèles 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 didacticiel.
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 en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. On peut le joindre à mitchell@4GuysFromRolla.com.