Parcourir l'intégralité des données d'un GridView

Signaler
Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007
-
 alex -
Bonjour,

J'ai un GridView dans lequel j'ai un Template field contenant un checkbox sur lequel agiront mes utilisateurs pour sélectionner ou non la donnée représentée par la ligne du GridView

<

asp:GridView
ID= "gvSeuils"
runat="server"
AllowPaging="True"
AllowSorting="True">

<Columns>

<asp:BoundField
DataField="Id"
HeaderText="Id"
SortExpression="Id">

<ItemStyle
HorizontalAlign="Center"
Width="50px"
/>

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:BoundField
DataField="Amenagement"
HeaderText="Am‚nagement"
SortExpression="Amenagement">

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:BoundField
DataField="Type"
HeaderText="Type"
SortExpression="Type">

<ItemStyle
Width="50px"
/>

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:BoundField
DataField="Code"
HeaderText="Code"
SortExpression="Code">

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:BoundField
DataField="Nom"
HeaderText="Nom"
SortExpression="Nom">

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:BoundField
DataField="Nature"
HeaderText="Nature"
SortExpression="Nature">

<ItemStyle
width="50px"
/>

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:BoundField
DataField="Valeur"
HeaderText="Valeur"
SortExpression="Valeur">

<ItemStyle
Width="50px"
HorizontalAlign="Right"
/>

<HeaderStyle
Font-Underline="True"
/>

</asp:BoundField>

<asp:TemplateField
InsertVisible="False"
ShowHeader="False"
>

<ItemStyle
HorizontalAlign ="Center"
Width= "10px"
/>


<HeaderStyle
Font-Underline="false"
/>

<ItemTemplate>

<asp:CheckBox
ID ="ckbFonction"
runat= "server"
/>


</ItemTemplate>

</asp:TemplateField>

</Columns>

</asp:GridView>

Je souhaite lors de la validation parcourir l'intégralité des pages affichées par ma GridView afin de récupérer ou non la sélection de ces CheckBox

Pour cela, je fais :

For

Each myRow As GridViewRow In gvSeuils.Rows

      If
CType(myRow.Cells(7).Controls(1), CheckBox).Checked
Then            seuilSelectionnee =

True

            Exit
For

      End
If

Next

Le souci, c'est que gvSeuils.Rows ne renvoie que le nombre de lignes affichées (10 pour moi) par la pagination, je ne parcours donc que les données de la page courante affichée

Je n'arrive pas à mettre la main sur la nom de la propriété permettant de parcourir intégralement toutes les lignes.

Merci d'avance

Yoan

17 réponses

Messages postés
745
Date d'inscription
mardi 30 novembre 2004
Statut
Membre
Dernière intervention
15 septembre 2009
4
Salut,

à defaut de trouver cette commande (je ne sais pas si ça existe), tu peux toujours parcourir toutes les pages de ta GridView...

C'est vrai que ça te fera 2 boucles imbriquées mais ça marchera.

<hr />
@+  
Messages postés
34
Date d'inscription
lundi 4 août 2003
Statut
Membre
Dernière intervention
17 juin 2008

Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007

Merci de ta réponse

Autant pour moi, je n'ai pas précisé que j'avais testé le parcours avec changement de page :

nbPage = gvSeuils.PageCount - 1

For indexPage
As
Integer = 0
To nbPage      gvSeuils.PageIndex = indexPage

      For
Each myRow
As GridViewRow
In gvSeuils.Rows

            If 
CType(myRow.Cells(7).Controls(1), CheckBox).Checked
Then                  ' traitement
            

End
If      
      Next      indexPage += 1

Next

Cette solution ne fonctionne malheureusement pas  Il ne tiens pas compte du changement de page et renvoie les données de la page courante...

D'ailleurs, dans la MSDN, il est écrit :

AllowPaging property to true), use the PageIndex property to determine the index of the currently displayed page. You can also use this property to programmatically change the displayed page.

Il n'est pas précisé que ça permet de parcourir l'intégralité du GridView "programmatically"

HELP
Messages postés
745
Date d'inscription
mardi 30 novembre 2004
Statut
Membre
Dernière intervention
15 septembre 2009
4
Regarde du côté de l'évènement RowDataBound de ton GridView.

<hr />
@+  
Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007

Merci drahcir et obel pour vos réponses.


@drahcir : j'ai parcourue la MSDN de RowDataBound : on ne parle pas de parcours de données

@obel : site fort intéressant, je garde précieusement le lien, mais pas de réponse à ma question
Messages postés
745
Date d'inscription
mardi 30 novembre 2004
Statut
Membre
Dernière intervention
15 septembre 2009
4
Protected






Sub
GridView1_RowDataBound(

ByVal
sender

As



Object
,

ByVal
e

As
System.Web.UI.WebControls.GridViewRowEventArgs)

Handles
GridView1.RowDataBound   If 
CType(e.Cells(7).Controls(1), CheckBox).Checked
Then

                  ' traitement
   


End



If      


End



Sub







<hr />

@+  
Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007

Merci, mais comme je l'explique dans mon premier message, l'idée est :
1) de proposer une liste d'environ 250 éléments affichés par page de 10 éléments
2) je laisse les utilisateurs sélectionner dans ces 25 pages les éléments qu'ils veulent
3) c'est lors de la validation de la page que je veux parcourir mon GridView pour récupérer la sélection

Donc, RowDataBound ne me permet pas de faire ceci

Je ne dois pas être le seul à vouloir faire cette manipulation élémentaire dans une IHM
Messages postés
745
Date d'inscription
mardi 30 novembre 2004
Statut
Membre
Dernière intervention
15 septembre 2009
4
et la validation de la page ne se fait pas à chaque changement de page?

<hr />
@+  
Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007

Je voudrais récupéré mes données à la validation définitive de ma page, pas sur un PostBack de changement de page d'un GridView.

Pourquoi ? Pour récupérer en une seule fois la liste des données sélectionnées.

Je comprends ce que tu me proposes. Le problème, c'est que comme on peut revenir plusieurs fois sur la même page pour cocher et décocher des éléments, ça oblige à faire des recherche dans une collection pour savoir si l'élément existe ou non dedans. Je te laisse imaginer les performances... (ma liste minimale est de 250 éléments)

Enfin, il me semble que RowDataBound est déclenché au chargement de la page, pas à sa validation :

Validation de la page => Load de la page suite au post back => chargement des données de la gridview => rowdatabound pour chaque ligne

Me trompège
Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007

J'ajoute une pécision à ma pensée du dessus

Si l'événement RowDataBound est bien au chargement de la page, suite au post-back, les données modifiées ne sont plus visibles dans le GridView car on a changé de page

Yoan
Messages postés
34
Date d'inscription
lundi 4 août 2003
Statut
Membre
Dernière intervention
17 juin 2008

j'ai vu un truc comme ça sur un post une fois mais avec un repeater

multiupdate ça s'appelle je peux t'envoyer un zip si tu veux

mais je crois que sur le forum c pas possible
obellantonio@hotmail.com
envoi et demain je t'envoi le zip sur ton mail
Messages postés
745
Date d'inscription
mardi 30 novembre 2004
Statut
Membre
Dernière intervention
15 septembre 2009
4
C'est bien ça, il y a un post back à chaque changement de page (il me semble en tout cas).

Regarde si tu n'as pas un moyen de ne pas générer de post back (je me demande s'il y a pas une propriété...)

Sinon pour rester dans le RowDataBound, tu peux toujours ajouter des lignes cochées dans une collection et tu feras ton traitement à la validation.
Le problème, c'est qu'à chaque fois ça t'oblige à tester qu'elles ne sont pas déjà résente dans ta collection avant de les ajouter...

Donc en terme de perf, c'est peut-être pas ce qu'il y a de mieux!!!

Si j'ai une autre idée, je t'en fais part... et si tu trouves, postes ta réponses c'est toujours intéressant

<hr />
@+  
Messages postés
1642
Date d'inscription
samedi 6 novembre 2004
Statut
Modérateur
Dernière intervention
28 avril 2011
2
Salut,

Attention, il faut bien comprendre que ASP.NET ne stocke rien entre deux Postback ! Et comme un changement de page du gridview nécessite un aller/retour serveur (donc un PostBack) pour charger les données suivantes, tu ne peux faire ta validation que pour chaque page, séparément des autres.

Une solution "simple" consisterait à stocker (en Session) un tableau contenant les IDs (ou ce que tu veux) identifiant les éléments "sélectionnés" sur l'ensemble des pages.
A chaque changement de page tu fais un .Add() pour chaque CheckBox cochée et un .Remove() sur chaque décochée (pas grave si l'élément n'existe pas, le Remove ne lève pas d'exception pour ça ; et de plus ça évite de vérifier si la collection ne contient pas déjà l'élément lors du Add() )
Pour l'évènement auquel il faut s'abonner, je dirais je PageIndexChanging, qui se produit au changement de page mais avant que le GridView ne fasse la requête pour récupérer les données suivantes (il contient donc toujours les anciennes données, et donc aussi les CheckBox cochées ou pas).
Et vu qu'on peut revenir plusieurs fois sur la même page, il faut que tes CheckBox conservent l'état qu'elles avaient, donc, dans le RowDataBound cette fois, là tu vas devoir faire une boucle sur le tableau pour re-remplir les CheckBox...

Ensuite à la validation finale (un click sur un bouton, ou ce que tu veux), après avoir également parcouru les lignes de la dernière page (ne pas l'oublier celle là, il n'y aura pas de PageIndexChanging de levé vu que tu ne changes pas de page ) tu sais quelles ont été les données sélectionnées et tu peux faire ce que tu veux avec...

(il y peut être plus simple mais je vois pas...)

Niveau perf, ce qui compte c'est que le nombre d'élements sélectionnés ne soit pas trop important, genre n'atteigne pas les 1000...
le nombre total d'éléments, ou le nombre par page, sont sans importance...

A++

<hr width="100%" size="2" />Nurgle (Antoine) - MSP
Messages postés
1642
Date d'inscription
samedi 6 novembre 2004
Statut
Modérateur
Dernière intervention
28 avril 2011
2
Un autre petit truc pour améliorer les perfs : stocke dans une autre variable Session un tableau contenant les numéros des pages déjà visitées. ça coute rien (un petit tableau d'int) mais ça te permet, dans le RowDataBound, de ne pas parcourir la collection pour re-remplir les CheckBox si la page n'a jamais été visité...
Avec peu de données ça changera pas grand chose, mais dès que tu auras pas mal d'éléments, ça évitera pleins de parcours inutiles de la collection...

ça fait quand même beaucoup de bordel pour pas grand chose... décidement, il doit y avoir un truc qui m'est passé sous le nez...

<hr width="100%" size="2" />Nurgle (Antoine) - MSP
Messages postés
18
Date d'inscription
mercredi 18 mai 2005
Statut
Membre
Dernière intervention
10 septembre 2007

Merci 375045 Nurgle pour tes réponses

J'avais en attendant mis en place la solution que tu proposes pour pouvoir avancer (hormis la mémorisation des pages visitées), j'avais l'impression que c'était du bricolage, mais je vois qu'apparemment, il n'y aurait pas d'autre solution...

Je ne coche pas ta réponse comme "Acceptée" car ce n'est pas la réponse exacte à ma question, puisque l'on ne parcourt pas de A à Z le GridView, mais par page avec des sauvegardes intermédiaires...

Je post mon code associé à ta réponse en dessous, si ça peut aider pour quelqu'un d'autres...

' l'objet que j'utilise pour mémoriser en session

Private
Property ObjetCourant()
As Profil

      Get

            Return
CType(Session(URL_PAGE_PROFIL & CLE_OBJET), Profil)

      End
Get

      Set(
ByVal value
As Profil)            Session(URL_PAGE_PROFIL & CLE_OBJET) = value

      End
Set

End
Property=> mon objet de type Profil contient une collection nommée "Seuils" fournissant les méthodes "Add", "Remove" et "Contains"
=> ce sont des objets de type "Seuil" que j'affiche dans mon GridView

' la gestion de l'événement "PageIndexChanging"
Protected

Sub gvSeuils_PageIndexChanging(
ByVal sender
As
Object,
ByVal e
As System.Web.UI.WebControls.GridViewPageEventArgs)
Handles gvSeuils.PageIndexChanging
' ici, le changement de page n'a pas encore eu lieu

EnregistreDonneesGridViewGvSeuils()

' fonction de mon API qui gére le tri et la pagination de mon GridView
GridViewHelper.HandlePageIndexChanging(gvSeuils, ViewState, e)    

End
Sub

' la gestion de l'événement "RowDataBound"
Protected

Sub gvSeuils_RowDataBound(ByVal sender AsObject, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvSeuils.RowDataBound

Dim myId
As
Integer

Dim mySeuil
As Seuil

If
Not e.Row.FindControl(
"ckbFonction")
Is
Nothing
Then

      ' l'id est en premiŠre position      
      If e.Row.Cells(0).Text <>
""Then            myId Integer.Parse(e.Row.Cells(0).Text)            mySeuil Seuil.Load(myId)

            If mySeuil
IsNot
Nothing
Then

                  CType(e.Row.FindControl(
"ckbFonction"), CheckBox).Checked = (
Me.ObjetCourant.Seuils.Contains(mySeuil))

            End
If

      End
If

End
If

End
Sub

Private

Sub EnregistreDonneesGridViewGvSeuils()

Dim myId
As
Integer

Dim mySeuil
As Seuil

For
Each myRow
As GridViewRow
In gvSeuils.Rows      ' je lis l'identifiant unique de ma donnée en début de ligne de mon GridView

      myId =

CInt(myRow.Cells(0).Text)
      ' j'utilise NHibernate, je charge mon objet complet à partir de son Id

      mySeuil = Seuil.Load(myId)    

      If
Not mySeuil
Is
Nothing
Then

            If
CType(myRow.Cells(7).Controls(1), CheckBox).Checked
Then

                  ' si checkbox coché, j'ajoute à la collection
                  Me.ObjetCourant.Seuils.Add(mySeuil)

            Else

                  ' si checkbox non coché, je supprime de la collection
                  Me.ObjetCourant.Seuils.Remove(mySeuil)

            End
If

      End
If

Next

End
Sub

Remarque : mon objet de type "Seuil" redéfini la méthode "Equals" pour que les fonctions "Add", "Remove" et "Contains" puissent fonctionner correctement

Enfin, lors de la validation de la page, j'appelle une nouvelle fois la fonction EnregistreDonneesGridViewGvSeuils pour mémoriser la sélection des CheckBox de la page courante.
Messages postés
34
Date d'inscription
lundi 4 août 2003
Statut
Membre
Dernière intervention
17 juin 2008

il y a qq1 qui peux regarder mes posts j'ai besoin d'aide pour une dropdown list imbriqué dans un repeater avec un where 'xxxx' dans la requete et je sèche grave !!!

Olivier

A+
Bonjour
Le sujet date beaucoup mais je n'ai pas trouvé de sujet plus recent sur le même problème

Je poste une petite solution très simple mais à confirmer par quelqu'un qui s'y connait un peu mieux que moi :

dans le codebehind
- mettre le parametre de la gridview allowpagging=false avant de parcourir la gridview
- faire un databind de la gridview
maintenant le foreach pourra parcourir l'ensemble des données


Après le for each(je ne sais pas si c'est necessaire ):
-remettre allowpagging=true
-faire un autre databind

Testé et ça fonctionne impec'.

Là où j'ai un doute, c'est que je ne sais pas si la fonction databind lie les donnés déjà chargées (idéalement c'est ce que je veux)
ou si elle fait appel à une requete bdd (et là c'est tout de suite moins interressant si on doit faire plusieurs fois une requête)

un avis ?

note : dans mon exemple, j'ai une griedview remplie par un ObjectDataSource qui fait appel à une requête SQL.
Je suis en C# mais je suppose que la partie .aspx est identique quel que soit le language

EDIT : un collègue m'a soufflé que dans mon cas je pouvais tout simplement parcourir mon datasource, effectivement c'est bien plus efficace