ASP.NET : GridView éditable

Il est possible d'éditer les données affichées dans un GridView. ASP.NET met en place des automatismes pour faciliter le travail du programmeur. Mais pour profiter de ces automatismes, il faut respecter certaines règles.

▼Publicité

Requête permettant de faire la mise à jour

La requête qui servira à effectuer la mise à jour doit être spécifiée dans la source de données (attribut UpdateCommand). Il peut s'agir d'une requête UPDATE ou d'une procédure stockée.

Dans tous les cas, il faut respecter les règles suivantes : 

  • La requête SELECT de la source de données associée au GridView doit aller chercher l'identifiant (ex : produit_id) et ce, même si l'identifiant n'est pas affiché. 
  • Le GridView doit utiliser la propriété DataKeyNames pour indiquer le nom du champ servant d'identifiant.
  • La requête UPDATE doit recevoir un paramètre pour chaque champ affiché dans la grille et un paramètre supplémentaire pour l'identifiant (ex : produit_id). Ce dernier sera utilisé dans le WHERE pour préciser quel enregistrement doit être modifié.
  • Le nom des paramètres dans la requête UPDATE doit correspondre exactement au nom des champs dans la ou les tables mises à jour. Si la mise à jour est effectuée à l'aide d'une procédure stockée, le nom des paramètres reçus par la procédure stockée doit correspondre au nom des champs dans la ou les tables mises à jour.

Puisque nous utiliserons les automatismes d'ASP.NET, il n'est pas nécessaire de définir les UpdateParameters pour la requête.

Lien permettant d'éditer directement dans la grille

L'attribut AutoGenerateEditButton du GridView permet d'ajouter automatiquement un lien « Modifier » pour chaque ligne de la grille. 

Voici un exemple de GridView présentant ce lien. Remarquez que l'apparence du lien a été modifiée via le CSS afin qu'il ne soit pas souligné.

GridView avec AutoGenerateEditButton

Lorsqu'un internaute cliquera sur un lien « Modifier », les informations de la ligne seront changées en contrôles éditables et le lien « Modifier » laissera la place aux liens « Mettre à jour » et « Annuler ». Un clic sur « Mettre à jour » exécutera automatiquement la requête précisée dans le UpdateCommand.

Remarquez qu'il est possible de laisser certains champs en lecture seule.

Édition dans un GridView

Voici le code permettant de générer ce GridView :

Fichier .aspx (ASP.NET)

<asp:GridView ID="gridViewProduits" runat="server" DataSourceID="dataSourceProduit" AllowSorting="true" DataKeyNames="prod_id"

AutoGenerateEditButton="true" AutoGenerateColumns="false" HeaderStyle-CssClass="entetegrille" AlternatingRowStyle-CssClass="lignesgrille">

   <Columns>

      <asp:BoundField DataField="prod_code"

         HeaderText="Code" SortExpression="prod_code" ReadOnly="true" />

      <asp:BoundField DataField="prod_nom"

         HeaderText="Nom" SortExpression="prod_nom" />

   </Columns>

</asp:GridView>

 

<asp:SqlDataSource ID="dataSourceProduit" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionStringVotreSite %>" 

   SelectCommand="SELECT prod_id, prod_code, prod_nom FROM produit ORDER BY prod_code"

   UpdateCommand="UPDATE produit SET prod_nom=@prod_nom WHERE prod_id=@prod_id">

</asp:SqlDataSource>    

Sélectionner, modifier ou supprimer un enregistrement

Les exemples précédents montrent comment modifier un enregistrement directement dans le GridView. Il est également possible de sélectionner un enregistrement ou de le supprimer. 

Voici un exemple :

Édition dans un GridView

Fichier .aspx (ASP.NET)

<asp:GridView ID="gridViewProduits" runat="server" DataSourceID="dataSourceProduit" AllowSorting="true" DataKeyNames="prod_id"

   AutoGenerateEditButton="true" AutoGenerateSelectButton="true" AutoGenerateDeleteButton="true"  

   AutoGenerateColumns="false" HeaderStyle-CssClass="entetegrille" AlternatingRowStyle-CssClass="lignesgrille"

   OnSelectedIndexChanged="gridViewProduits_SelectedIndexChanged">

   <Columns>

      <asp:BoundField DataField="prod_code"

         HeaderText="Code" SortExpression="prod_code" ReadOnly="true" />

      <asp:BoundField DataField="prod_nom"

         HeaderText="Nom" SortExpression="prod_nom" />

   </Columns>        

</asp:GridView>

 

<asp:SqlDataSource ID="dataSourceProduit" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionStringVotreSite %>" 

   SelectCommand="SELECT prod_id, prod_code, prod_nom FROM produit ORDER BY prod_code"

   UpdateCommand="UPDATE produit SET prod_nom=@prod_nom WHERE prod_id=@prod_id"

   DeleteCommand="DELETE FROM produit WHERE prod_id=@prod_id">

</asp:SqlDataSource>

À la base, les liens pour modifier et supprimer une ligne ne nécessitent aucun code C#. Tout peut se passer dans le fichier de balises. 

Il faudra cependant coder le travail à effectuer sur le lien pour sélectionner. L'événement OnSelectedIndexChanged peut être utilisé pour cela.

Ex :

Fichier .aspx.cs (ASP.NET avec C#)

protected void gridViewProduits_SelectedIndexChanged(object sender, EventArgs e)

{

   // Retrouver la référence au GridView pour lequel on vient de sélectionner un élément

   // Cette instruction est ici optionnelle mais dans le cas de tableaux imbriqués, elle deviendra nécessaire

   GridView gridView = (GridView)sender;

   // Retrouver l'identifiant de la ligne sélectionnée

   int id = (int)gridView.DataKeys[gridView.SelectedIndex].Value;

 

   // On peut maintenant effectuer des manipulations à l'aide de ce id.

   ...

 

   // Retrouver la ligne sélectionnée

   GridViewRow row = gridView.SelectedRow;

 

   // On peut maintenant manipuler informations de cette ligne. 

   // La cellule 0 contient les liens pour éditer, supprimer ou sélectionner. 

   // La cellule 1 contient le premier BoundField.

   String code = row.Cells[1].Text;

   ...

   // La sélection d'une ligne dans une grille se termine généralement par l'affichage d'une autre page

   Response.Redirect(...);

}

Meilleure technique pour sélectionner un enregistrement

Lorsqu'on travaille avec un lien généré par le code ASP.NET, le code envoyé au client ressemble à ceci :

HTML

<a href="javascript:__doPostBack(&#39;ctl00$contentPlaceHolderContenu$gridViewProduits&#39;,&#39;Select$0&#39;)">Sélectionner</a>

Le code Javascript ainsi généré s'occupe de recharger la page, ce qui donne la possibilité d'effectuer du traitement côté serveur. De façon générale, le code s'occupera d'effectuer un traitement quelconque puis fera un Response.Redirect pour afficher une autre page Web.

Par contre, puisque lien déclenche une fonction Javascript, certaines fonctionnalités gérées par le navigateur ne sont plus disponibles. Par exemple, il n'est pas possible d'effectuer un Ctrl+clic sur le lien pour l'ouvrir dans un autre onglet. Le clic droit donnant accès à un menu contextuel, s'il est toujours disponible, donnera des résultats inattendus.

C'est pourquoi, lorsque le lien « Sélectionner » ne sert qu'à mener vers une autre page, il est préférable de travailler avec un simple lien HTML ou, mieux encore, avec un HyperLink, qui donne plus de contrôle sur le lien.

Ex :

Fichier .aspx (ASP.NET)

<asp:GridView ID="gridViewProduits" runat="server" DataSourceID="dataSourceProduit" AllowSorting="true" DataKeyNames="prod_id"

   AutoGenerateEditButton="true" AutoGenerateSelectButton="false" AutoGenerateDeleteButton="true"

   AutoGenerateColumns="false" HeaderStyle-CssClass="entetegrille" AlternatingRowStyle-CssClass="lignesgrille"

   OnRowDataBound="gridViewProduits_RowDataBound">

   <Columns>

      <asp:TemplateField>

         <ItemTemplate>

            <%--Il sera possible de faire Ctrl+Clic ou clic droit pour ouvrir la page dans un nouvel onglet--%>

            <asp:HyperLink runat="server" ID="hyperLinkSelectionner" Text="Sélectionner" ToolTip="Détails du produit"></asp:HyperLink>

         </ItemTemplate>

      </asp:TemplateField>

      <asp:BoundField DataField="prod_code"

         HeaderText="Code" SortExpression="prod_code" ReadOnly="true" />

      <asp:BoundField DataField="prod_nom"

         HeaderText="Nom" SortExpression="prod_nom" />

   </Columns>

</asp:GridView>

Puisque chaque ligne du GridView doit mener à la fiche détaillée correspondant à l'élément affiché sur la ligne, il faudra gérer par programmation la page où mènera le lien.

Fichier .aspx.cs (ASP.NET avec C#)

protected void gridViewProduits_RowDataBound(object sender, GridViewRowEventArgs e)

{

   if (e.Row.RowType == DataControlRowType.DataRow)

   {

      // Ajuster le lien pour afficher la fiche du produit sélectionné

      String prod_id = ((GridView)sender).DataKeys[e.Row.RowIndex].Values["prod_id"].ToString();

      HyperLink hyperLinkSelectionner = (HyperLink)e.Row.FindControl("hyperLinkSelectionner");

      hyperLinkSelectionner.NavigateUrl = "DetailsProduit.aspx" + "?prod_id=" + prod_id;

   }

}

Bind() vs Eval()

Dans un <ItemTemplate>, il est d'usage d'avoir recours à Eval() pour donner la valeur aux contrôles. 

Dans un <EditItemTemplate>, il faut plutôt utiliser Bind() puisque Eval() ne permet pas de retourner la valeur à la commande Update, ce qui ferait planter le site lors de l'enregistrement.

Eval() est plus rapide que Bind() mais ne peut pas être utilisé en édition.

Ex :

Fichier .aspx (ASP.NET)

<asp:GridView ID="gridViewProduits" ...>

   <Columns>

      <asp:BoundField DataField="produit_code"

         HeaderText="Code" SortExpression="produit_code" ReadOnly="true" />

      <asp:TemplateField HeaderText="Nom">

            <ItemTemplate>

                <asp:Label ID="labelNom" runat="server" Text='<%# Eval("produit_nom") %>' />

            </ItemTemplate>

            <EditItemTemplate>

               <asp:TextBox ID="textBoxNom" runat="server" MaxLength="50" Text='<%# Bind("produit_nom") %>' />

               <asp:RequiredFieldValidator ID="validationNomRequis" runat="server" ControlToValidate="textBoxNom"

                  ErrorMessage="requis" CssClass="erreurvalidateur" SetFocusOnError="True" />

            </EditItemTemplate>

        </asp:TemplateField>

    </Columns>

</asp:GridView>

Eval() vs ((DataRowView)Container.DataItem) 

Si vous souhaitez utiliser une technique encore plus rapide, remplacez Eval() par ((DataRowView)Container.DataItem). C'est plus long à taper mais vous obtiendrez un léger gain de performance.

Ex :

Fichier .aspx (ASP.NET)

<asp:Label ID="labelNom" runat="server" Text='<%# ((DataRowView)Container.DataItem)["produit_nom"] %>' />

Actions déclenchées par un clic sur un lien ou sur un bouton dans un GridView

Dans le GridView, chaque bouton ou lien présent sur une ligne de données aura un nom de commande associé (CommandName). 

Lorsqu'on utilise les attributs AutoGenerateEditButton="true", AutoGenerateDeleteButton="true", etc., la commande appropriée est automatiquement associée au bouton ou au lien. Il est toutefois possible d'utiliser ces mêmes commandes lorsque nous ajoutons des boutons ou des liens dans la grille d'une autre façon.

Voici un résumé des commandes de base que vous pouvez associer à vos boutons ou à vos liens dans un GridView.

Code pour ajouter le lien ou le bouton Valeur de CommandName Action déclenchée
Édition de données
Fichier .aspx (ASP.NET)

<asp:Gridview ... AutoGenerateEditButton="true">

ou

Fichier .aspx (ASP.NET)

<asp:CommandField ... ShowEditButton="true">

ou

Fichier .aspx (ASP.NET)

<asp:TemplateField>

   <ItemTemplate>

      <asp:ImageButton ...

         CommandName="Edit">

         ...

   </ItemTemplate>

   ...

</asp:TemplateField>

Edit

Change le mode d'affichage pour que les contrôles soient éditables.

Affiche les boutons pour enregistrer ou annuler.

Enregistrement des données éditées

Bouton ou lien affiché automatiquement lorsque la ligne est en édition

ou

Fichier .aspx (ASP.NET)

<asp:TemplateField>

   ...

   <EditItemTemplate>

      <asp:ImageButton ...

         CommandName="Update">

         ...

   </EditItemTemplate> 

</asp:TemplateField>

Update

DataSource.Update()

Change le mode d'affichage pour que les contrôles ne soient plus éditables.

Cache les boutons pour enregistrer ou annuler.

Annulation des modifications

Bouton ou lien affiché automatiquement lorsque la ligne est en édition

ou

Fichier .aspx (ASP.NET)

<asp:TemplateField>

   ...

   <EditItemTemplate>

      <asp:ImageButton ...

         CommandName="Cancel">

         ...

   </EditItemTemplate> 

</asp:TemplateField>

Cancel

Change le mode d'affichage pour que les contrôles ne soient plus éditables sans tenir compte des modifications apportées aux données .

Cache les boutons pour enregistrer ou annuler.

Suppression de donnnées
Fichier .aspx (ASP.NET)

<asp:Gridview ... AutoGenerateDeleteButton="true">

ou

Fichier .aspx (ASP.NET)

<asp:CommandField ... ShowDeleteButton="true">

ou

Fichier .aspx (ASP.NET)

<asp:TemplateField>

   <ItemTemplate>

      <asp:ImageButton ...

         CommandName="Delete">

         ...

   </ItemTemplate>

   ...

</asp:TemplateField>

Delete DataSource.Delete()
Sélection d'une ligne
Fichier .aspx (ASP.NET)

<asp:Gridview ... AutoGenerateSelectButton="true">

ou

Fichier .aspx (ASP.NET)

<asp:CommandField ... ShowSelectButton="true">

ou

Fichier .aspx (ASP.NET)

<asp:TemplateField>

   <ItemTemplate>

      <asp:ImageButton ...

         CommandName="Select">

         ...

   </ItemTemplate>

   ...

</asp:TemplateField>

Select Change la valeur de la propriété SelectedIndex du GridView.

Effectuer un traitement avant l'action préprogrammée

Il est possible d'ajouter du code à exécuter lorsque le lien ou le bouton est cliqué en créant un gestionnaire associé à l'événement OnRowCommand. Le code présent dans ce gestionnaire sera exécuté AVANT l'action préprogrammée pour chaque nom de commande.

Ex :

Fichier .aspx (ASP.NET)

<asp:GridView ID="gridViewProduits" ... OnRowCommand="GridViewProduits_RowCommand">

   ...

</asp:GridView>

Fichier .aspx.cs (ASP.NET avec C#)

protected void gridViewProduits_RowCommand(Object sender, GridViewCommandEventArgs e)

{

   if (e.CommandName == "Select")

   {

      ...  

   }

   else if (e.CommandName == "Edit")

   {

      ...

   }

   ...

}

Changer les liens par des images dans un GridView éditable

Dans sa forme la plus simple, le GridView affiche le mot « Modifier » sur chaque ligne du GridView pour permettre d'éditer les données. ll est possible de modifier ce lien par des images pour obtenir un visuel plus agréable.

GridView avec Liens transformés en images

Il existe plusieurs techniques pour parvenir à ce résultat. La plus polyvalente consiste à utiliser un TemplateField dans lequel on placera des ImageButton. Ceci nous permettra notamment d'ajouter une bulle d'aide, ce qui n'aurait pas été possible avec les autres techniques.

Avec cette technique, il faut absolument préciser le CommandName associé à l'image.

Fichier .aspx (ASP.NET)

<asp:GridView ...>

   <Columns>

      <asp:TemplateField>

         <ItemTemplate>

            <asp:ImageButton runat="server" ID="imageButtonModifier" imageUrl="medias/commun/BoutonModifier.png"

               CommandName="Edit" />

         </ItemTemplate>

         <EditItemTemplate>

            <asp:ImageButton runat="server" ID="imageButtonEnregistrer" imageUrl="medias/commun/BoutonEnregistrer.png"

               CommandName="Update" />

            <asp:ImageButton runat="server" ID="imageButtonAnnuler" imageUrl="medias/commun/BoutonAnnuler.png"

               CommandName="Cancel" />

         </EditItemTemplate>

      </asp:TemplateField>

      <asp:BoundField DataField="prod_code"

         HeaderText="Code" SortExpression="prod_code" ReadOnly="true" />

      <asp:BoundField DataField="prod_nom"

         HeaderText="Nom" SortExpression="prod_nom" />

   </Columns>

</asp:GridView>

Action personnalisée sur une ligne de données

Dans la majorité des cas, les actions gérées automatiquement par ASP.NET (Select, Edit, Delete, etc.) répondront à vos besoin. 

Par contre, il arrivera des cas où vous souhaiterez effectuer une toute autre action, comme par exemple changer l'ordre d'un enregistrement afin qu'il apparaisse après l'enregistrement suivant.

Vous devez pour cela :

  • Ajouter un attribut CommandArgument qui permettra d'envoyer l'index de la ligne sélectionnée dans le paramètre GridViewCommandEventArgs
  • Donner un CommandName différent de ceux gérés automatiquement par ASP.NET
  • Coder le traitement dans l'événement OnRowCommand

Ex :

Fichier .aspx (ASP.NET)

<asp:GridView ... OnRowCommand="gridViewProduits_RowCommand">

   <Columns>

      <asp:TemplateField>

         <ItemTemplate>

            <asp:ImageButton runat="server" ID="imageButtonDescendre" imageUrl="medias/commun/BoutonDescendre.png"

               CommandName="Descendre" CommandArgument="<%# Container.DataItemIndex %>" />

         </ItemTemplate>

      </asp:TemplateField>

      <asp:BoundField DataField="prod_code"

         HeaderText="Code" SortExpression="prod_code" />

      <asp:BoundField DataField="prod_nom"

         HeaderText="Nom" SortExpression="prod_nom" />

   </Columns>

</asp:GridView>

Fichier .aspx.cs (ASP.NET avec C#)

protected void gridViewProduits_RowCommand(Object src, GridViewCommandEventArgs e)

{

    if (e.CommandName == "Descendre")

    {

       // Retrouver l'index de la ligne sur laquelle on a cliqué

       // Puisqu'on travaille avec un ImageButton, ceci fonctionne seulement si le ImageButton s'occupe d'initialiser

       // l'index dans le CommandArgument :  <asp:ImageButton ... CommandArgument="<%# Container.DataItemIndex %>" />

       int index = Convert.ToInt32(e.CommandArgument);

       gridViewProduits.SelectedIndex = index;

 

       // Retrouver les données de la ligne choisie

       int prod_id = Convert.ToInt32(gridViewProduits.SelectedDataKey[0]);

      ...

    }

}

Ajustement juste avant l'enregistrement dans le GridView (e.NewValues)

Lorsqu'on effectue une mise à jour à partir d'un GridView, il arrive qu'on ait à modifier une valeur avant qu'elle soit enregistrée. Par exemple, on pourrait enregistrer une image par défaut lorsqu'aucune image n'est fournie.

Puisque la mise à jour à partir d'un GridView utilise les automatismes d'ASP.NET, il n'est pas possible de modifier la valeur d'un paramètre à l'aide de DataSource.UpdateParameters. Plutôt, on travaillera avec un tableau des données à enregistrer qui est disponible via le paramètre e dans l'événement OnRowUpdating du GridView.

Cette technique permet donc de modifier une valeur avant de l'enregistrer ou encore de donner une valeur par défaut.

Dans le cas où une valeur à enregistrer ne serait carrément pas lue dans le GridView, e.NewValue permettra à la fois de déclarer le paramètre et de l'initialiser. 

Ceci sera également utile pour recevoir la valeur d'un paramètre OUTPUT lorsque le UPDATE est réalisé à l'aide d'une procédure stockée.

Ex :

Fichier .aspx.cs (ASP.NET avec C#)

protected void gridViewProduits_RowUpdating(object sender, GridViewUpdateEventArgs e)

{

    if (e.NewValues["produit_prix"] != null)

    {

        // Transforme la chaîne en une valeur décimale.

        // Enlève le signe monétaire s'il était présent.

        // Transforme le séparateur de décimales, selon la culture utilisée, en point.

        e.NewValues["produit_prix"] = decimal.Parse(e.NewValues["produit_prix"].ToString(), System.Globalization.NumberStyles.Currency);

    }

}

Attention : vous devez utiliser les événements du GridView et non ceux du DataSource. Vous devez également vous assurer que le champ que vous désirez modifier par programmation soit effectivement utilisé dans la requête UPDATE de la source de données.

DetailsView

Le fonctionnement est très semblable lorsque vous utilisez un DetailsView pour insérer un enregistrement ou pour le modifier. Cependant, dans le cas de l'insertion, on travaillera avec e.Values et non avec e.NewValues.

Ex :

Fichier .aspx.cs (ASP.NET avec C#)

protected void detailsViewProduit_ItemInserting(object sender, DetailsViewInsertEventArgs e)

{

    // si aucune image n'a été fournie, on enregistre l'image par défaut

    if (e.Values["produit_image"] == null)

    {

        e.Values["produit_image"] = "imagemanquante.png";

    }

}

Vérifier si l'opération sur la BD a réussi

Lorsque vous éditez les données directement dans un GridView, vous pouvez contrôler ce qui se passe immédiatement après que la requête UPDATE ait été exécutée grâce à l'événement OnRowUpdated

Un incontournable qui devrait toujours être mis en place : s'assurer que la requête a pu être réalisée sur le serveur. Par exemple, que doit-il se passer si on tente d'enregistrer dans un champ numérique une valeur non numérique ? Dans le OnRowUpdated, on saura que la requête a fonctionné en testant e.Exception.

Il faudra toujours traiter ce cas pour assurer qu'aucune validation ne nous a échappée. Par exemple, si on permet la modification du code d'usager lors de l'édition du profil de l'usager, il est facile de s'assurer que le code n'est pas resté à blanc. Par contre, il faut également s'assurer que le code entré n'est pas déjà utilisé. Ceci peut se faire assez facilement en ajoutant le traitement nécessaire sur le clic du bouton. Par contre, si deux usager tentent de donner en même temps la même valeur à leur code d'usager, un des deux pourrait avoir le OK lorsque le code fait la validation mais ça ne fonctionnera pas lorsque le code tentera de faire le UPDATE s'il y a un index unique sur ce champ. Notre e.Exception permettra de rattraper cette erreur.

Ex :

Fichier .aspx (ASP.NET)

<asp:GridView ...OnRowUpdated=gridViewProduits_RowUpdated">

    ...

</asp:GridView>

Fichier .aspx.cs (ASP.NET avec C#)

void gridViewProduits_RowUpdated(Object sender, GridViewUpdatedEventArgs e)

{

   if(e.Exception == null)

   {

      labelMessage.Text = "Les données ont été enregistrées avec succès.";

   }

   else

   {

      // cette instruction est essentielle pour ne pas que le programme plante

      e.ExceptionHandled = true;  

 

      labelMessage.Text = "Un problème a empêché l'enregistrement des données.";

      ... // autre traitement à faire si nécessaire

   }

}

Liste déroulante à l'intérieur d'un GridView

Le DropDownList est le contrôle idéal pour les clés étrangères. Il permettra par exemple d'afficher la description d'une catégorie plutôt que de forcer l'utilisateur à se rappeler du code qui est enregistré dans la table des produits, code qu'il ne devrait d'ailleurs même pas connaître puisqu'il s'agit d'une valeur utilisée seulement à l'interne. 

Il est possible d'intégrer un DropDownList dans un GridView, comme dans l'exemple suivant. 

GridView avec un DropDownList

Voici une façon de parvenir à un tel résultat.

Ex :

Fichier .aspx (ASP.NET)

<asp:GridView ID="gridViewProduits" runat="server" DataSourceID="dataSourceProduit" 

   DataKeyNames="prod_id" AutoGenerateEditButton="true" AllowSorting="true" 

   OnRowUpdating="gridViewProduits_RowUpdating" AutoGenerateColumns="false" ...>

   <Columns>

      <asp:BoundField DataField="prod_code"

         HeaderText="Code" SortExpression="prod_code" ReadOnly="true" />

      <asp:BoundField DataField="prod_nom" HeaderText="Nom"

         SortExpression="prod_nom" />

      <asp:TemplateField HeaderText="Prix" SortExpression="prod_prix" ItemStyle-CssClass="colonneprix"> 

         <ItemTemplate>

            <asp:Label ID="labelPrix" runat="server" Text='<%# Eval("prod_prix", "{0:C2}") %>'></asp:Label>

         </ItemTemplate>

         <EditItemTemplate>     

            <asp:TextBox ID="textBoxPrix" runat="server" Text='<%# Bind("prod_prix", "{0:F2}") %>' />

            <asp:RegularExpressionValidator ID="validateurPrix" runat="server"  ControlToValidate="textBoxPrix" 

               ValidationExpression="^\d{0,6}(\,\d{0,2})?$" ErrorMessage="!" CssClass="erreurvalidateur" /> 

         </EditItemTemplate>

      </asp:TemplateField>

      <asp:TemplateField HeaderText="Catégorie" SortExpression="cat_description">

         <ItemTemplate>

            <asp:Label ID="labelCategorie" runat="server" Text='<%# Eval("cat_description") %>'></asp:Label>

         </ItemTemplate>

         <EditItemTemplate>

            <asp:DropDownList ID="dropDownListCategories" runat="server" DataSourceID="dataSourceCategorie" 

               DataTextField="cat_description" DataValueField="cat_id

               SelectedValue='<%# Bind("prod_cat_id") %>' >

            </asp:DropDownList>

         </EditItemTemplate>

      </asp:TemplateField>

   </Columns>

</asp:GridView>

 

<asp:SqlDataSource ID="dataSourceProduit" runat="server" 

   ConnectionString="<%$ ConnectionStrings:ConnectionStringVotreSite %>"

   SelectCommand="SELECT prod_idprod_codeprod_nom, prod_prix, prod_cat_id, cat_description FROM produit 

   INNER JOIN categorie ON cat_id=prod_cat_id ORDER BY prod_code"

   UpdateCommand="UPDATE produit SET prod_nom=@prod_nom, prod_prix=@prod_prix, prod_cat_id=@prod_cat_id

   WHERE prod_id=@prod_id" >

</asp:SqlDataSource>

<asp:SqlDataSource ID="dataSourceCategorie" runat="server" 

   ConnectionString="<%$ ConnectionStrings:ConnectionStringVotreSite %>"

   SelectCommand="SELECT cat_id,cat_description FROM categorie ORDER BY cat_description">

</asp:SqlDataSource>

Remarquez la présence de l'attribut OnRowUpdating. Il devient nécessaire dans le cas où un nombre avec décimales est saisi dans la grille. Le gestionnaire d'événement associé permettra de convertir les virgules décimales en points décimaux, qui est le seul séparateur accepté par MS SQL. Consultez la page sur les principaux événements du GridView pour plus d'information.

Remarquez également que lorsque le prix est édité, on lui attribut le format {0:F2} afin que le symbole monétaire n'apparaisse pas.

Dernière remarque importante : dans un <ItemTemplate>, il est d'usager d'avoir recours à Eval() pour donner la valeur aux contrôles. Dans un <EditItemTemplate>, il faut plutôt utiliser Bind() puisque Eval() ne permet pas de retourner la valeur à la commande Update, ce qui ferait planter le site lors de l'enregistrement.  Eval() est donc plus rapide que Bind() mais ne peut pas être utilisé en édition.

Pour plus d'information

« GridView, classe ». MSDN. http://msdn.microsoft.com/fr-fr/library/system.web.ui.webcontrols.gridview(v=VS.100).aspx

MITCHELL Scott. « Accessing and Updating Data in ASP.NET: Customizing the Editing Interface ». 4GuysFromRolla. http://aspnet.4guysfromrolla.com/demos/printPage.aspx?path=/articles/080807-1.aspx

« Databinding in Templates ». ASP.NET Quickstart Tutorials. http://quickstarts.asp.net/QuickStartv20/%28A%28okQqLaJnvXB9rnXWf_K7m_om-Zx0BYsOsJJrM20f_1axzwx5gnMNCvGwLWtxW8LNMqVbI9ES78LdxbvwHW6g0RWFcIzRzsq60%29%29/aspnet/doc/data/templates.aspx

« Modification des données dans un contrôle serveur Web GridView ». MSDN. http://msdn.microsoft.com/fr-fr/library/c4245bb4.aspx

« GridView Examples for ASP.NET 2.0: Editing the Underlying Data in a GridView ». MSDN. http://msdn.microsoft.com/en-us/library/ms972948.aspx

« GridView.RowCommand, événement ». MSDN. http://msdn.microsoft.com/fr-ca/library/system.web.ui.webcontrols.gridview.rowcommand.aspx

« Bind Dropdown Field In Gridview EditItemTemplate ». The Daily Reviewer. http://thedailyreviewer.com/dotnet/view/bind-dropdown-field-in-gridview-edititemtemplate-103402364

« GridViewUpdateEventArgs.NewValues, propriété ». MSDN. https://msdn.microsoft.com/fr-fr/library/system.web.ui.webcontrols.gridviewupdateeventargs.newvalues(v=vs.110).aspx

« GridViewUpdateEventArgs.OldValues, propriété ». MSDN. https://msdn.microsoft.com/fr-fr/library/system.web.ui.webcontrols.gridviewupdateeventargs.oldvalues(v=vs.110).aspx

« DetailsViewInsertEventArgs.Values, propriété ». MSDN. https://msdn.microsoft.com/fr-ca/library/system.web.ui.webcontrols.detailsviewinserteventargs.values(v=vs.110).aspx

« DetailsViewUpdateEventArgs.NewValues, propriété ». MSDN. https://msdn.microsoft.com/fr-ca/library/system.web.ui.webcontrols.detailsviewupdateeventargs.newvalues(v=vs.110).aspx

« DetailsViewUpdateEventArgs.OldValues, propriété ». MSDN. https://msdn.microsoft.com/fr-ca/library/system.web.ui.webcontrols.detailsviewupdateeventargs.oldvalues(v=vs.110).aspx

Merci de partager ! Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInPin on PinterestShare on StumbleUponEmail this to someone
Catégories