Cocher / décocher tous les enregistrements d’une GridView
Objectifs:
- Manipuler le contrôle serveur GridView
- Associer le contrôle GridView avec une source de données de type SqlDataSource
- Récupérer les données d'un contrôle serveur en code-behind et avec Javascript
Énoncé:
Créer une page ASP.Net qui propose à l’utilisateur de cocher ou décoder en un clic tous les enregistrements affichés dans une grille (GridView) en utilisant des cases à cochés (CheckBox).
Implémenter cette fonctionnalité dans l'interface de l’exercice Suppression de plusieurs lignes d’une GridView avec CheckBox en utilisant deux manières :
- Avec les évènements C# en code-behind
- Avec JavaScript pour éviter les PostBack
Remarque:
Si au moins une case est décochée il faut décocher la case d'entête sinon il faut la cocher.
Alors il faut prévoir les deux cas suivants :
- Si l’utilisateur clic sur la case de l’entête « Cocher tous » puis décoche une case de la liste, il faut décocher la case d'entête.
- S’il coche toutes les cases manuellement il faut activer la case de l’entête « Cocher tous ».
Solution avec code-behind C#
Pour commencer, il faut utiliser le contrôle GridView et l'associer à une source de données puis ajouter une colonne avec une case à cocher dans l’entête et une case à cocher pour chaque ligne.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4" DataKeyNames="Id" DataSourceID="SqlDataSource1" EmptyDataText="Il n'y a aucun enregistrement de données à afficher." ForeColor="#333333" GridLines="None" BorderStyle="Solid"> <AlternatingRowStyle BackColor="White" ForeColor="#284775" /> <Columns> <asp:TemplateField HeaderText="Action"> <HeaderTemplate> <asp:CheckBox ID="CheckBox1" OnCheckedChanged="CheckBox1_CheckedChanged" AutoPostBack="True" runat="server" /> </HeaderTemplate> <ItemTemplate> <asp:CheckBox ID="CheckBox2" OnCheckedChanged="CheckBox2_CheckedChanged" AutoPostBack="True" runat="server"/> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="Id" HeaderText="Id" ReadOnly="True" SortExpression="Id" /> <asp:BoundField DataField="Nom" HeaderText="Nom" SortExpression="Nom" /> <asp:BoundField DataField="Prenom" HeaderText="Prenom" SortExpression="Prenom" /> <asp:BoundField DataField="Adresse" HeaderText="Adresse" SortExpression="Adresse" /> <asp:BoundField DataField="Ville" HeaderText="Ville" SortExpression="Ville" /> </Columns> <EditRowStyle BackColor="#999999" /> <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /> <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /> <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" /> <RowStyle BackColor="#F7F6F3" ForeColor="#333333" /> <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" /> <SortedAscendingCellStyle BackColor="#E9E7E2" /> <SortedAscendingHeaderStyle BackColor="#506C8C" /> <SortedDescendingCellStyle BackColor="#FFFDF8" /> <SortedDescendingHeaderStyle BackColor="#6F8DAE" /> </asp:GridView> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:gestionCmdConnectionString1 %>" SelectCommand="SELECT [Id], [Nom], [Prenom], [Adresse], [Ville] FROM [Clients]"> </asp:SqlDataSource>
Dans le code ASPX généré, on a fait appel aux fonctions CheckBox1_CheckedChanged et CheckBox2_CheckedChanged qui correspondent à l'événement onCheckedChanged de la case à cocher de l’entête et du case à cocher de chaque ligne. (N'oubliez pas d'activer la propriété AutoPostBack des deux CheckBox!)
protected void CheckBox1_CheckedChanged(object sender, EventArgs e) { //Récupérer le checkbox qui a déclenché l'événement (la case de l'entete) CheckBox chkHead = (CheckBox)sender; //ou CheckBox chkHead = (GridView1.HeaderRow.FindControl("CheckBox1") as CheckBox); foreach (GridViewRow row in GridView1.Rows) { //Récupérer le checkbox de chaque ligne CheckBox chk = (row.Cells[0].FindControl("CheckBox2") as CheckBox); //Cocher le checkbox de la ligne courante selon l'état de la case de l'entete if (chkHead.Checked) { chk.Checked = true; } else { chk.Checked = false; } } } protected void CheckBox2_CheckedChanged(object sender, EventArgs e) { //Récupérer le checkbox de l'entete CheckBox chkHead = (GridView1.HeaderRow.FindControl("CheckBox1") as CheckBox); bool check = true; foreach (GridViewRow row in GridView1.Rows) { //Récupérer le checkbox de chaque ligne CheckBox chk = (row.Cells[0].FindControl("CheckBox2") as CheckBox); //Si au moins une case est décoché arrêter la boucle if (!chk.Checked) { check = false; break; } } chkHead.Checked = check; }
Solution avec JavaScript
Cette solution permet d'éviter des allez-retour vers le serveur puisque le code JavaScript sera exécuté côté client. Pour cela on a remplacé les procédures C# de l'événement CheckedChanged par deux fonctions JavaScript qui correspondent aux clic sur les deux CheckBox:
<asp:TemplateField HeaderText="Action"> <HeaderTemplate> <asp:CheckBox ID="CheckBox1" onclick="Cocher_Tous(this);" runat="server" /> </HeaderTemplate> <ItemTemplate> <asp:CheckBox ID="CheckBox2" onclick="Case_Click(this);" runat="server"/> </ItemTemplate> </asp:TemplateField>
Les fonctions JavaScript à mettre dans la balise head:
<script type = "text/javascript"> function Cocher_Tous(objRef) { //Récupérer l'objet GridView à partir de son ID var GridView = document.getElementById("<%= GridView1.ClientID%>"); //Récupérer tous les éléments input du GridView var inputList = GridView.getElementsByTagName("input"); for (var i=0;i<inputList.length;i++) { //Récupérer la ligne à partir de son checkbox var row = inputList[i].parentNode.parentNode; if(inputList[i].type == "checkbox" && objRef != inputList[i]) { if (objRef.checked) { //Si la case de l'entete est cocher //cocher toutes les cases inputList[i].checked=true; } else { inputList[i].checked=false; } } } } function Case_Click(objRef) { //Récupérer la ligne à partir de son checkbox var row = objRef.parentNode.parentNode; //Récupérer la référence du GridView var GridView = row.parentNode; //ou var GridView = document.getElementById("<%= GridView1.ClientID%>"); //Récupérer tous les éléments input du GridView var inputList = GridView.getElementsByTagName("input"); //Le premier élément est la case d'entete var headerCheckBox = inputList[0]; var checked = true; for (var i = 1; i < inputList.length; i++) { if (inputList[i].type == "checkbox") { if (!inputList[i].checked) { checked = false; break; } } } headerCheckBox.checked = checked; } </script>
L'instruction :
<%= GridView1.ClientID%>
permet de récupérer l'ID du contrôle GridView1 après génération du code HTML.