Evenement sur la scrollbar d'un DataGridView

Gorgonzovale Messages postés 4 Date d'inscription mercredi 29 janvier 2014 Statut Membre Dernière intervention 27 février 2014 - Modifié par Whismeril le 27/02/2014 à 18:07
Whismeril Messages postés 19034 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 2 mai 2024 - 27 févr. 2014 à 20:55
Bonjour, voici mon problème:
Dans mon form, j'ai une DataGridview qui est liée à une DataTable en local par BindingSource. Cette table se remplit en allant lire un bloc de données dans un fichier binaire.
Ce que je veux faire, c'est recharger ma DataTable en allant lire dans le fichier source lorsque je scrolle sur ma DataGridView.
Plus précisément, afin de laisser la liberté de scroller vers le haut, je veux charger dans la DataTable les lignes de n à m et afficher dans la DataGridView les lignes de n+10 à n+10+size_window en utilisant (du moins, c'est mon idée) la propriété FirstDisplayedScrollingIndex = n+10

Voici ma tentative:

first_displayed est l'index absolu(pour l'ensemble des données) de la première ligne dans la GridView avant l'évenement.
blockIndex et le 'n'dont je parlais, la première ligne du bloc source à charger dans la Table.

private void maGridView_Scroll(object sender, ScrollEventArgs e)
            {
                if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
                {
                    
                        int y = maGridView.FirstDisplayedScrollingRowIndex;

                         if (first_displayed <= 10)  // condition aux limites
                        {
                            first_displayed = y;
                            if (y <= 10)
                            {
                                blockIndex = 0;
                            }
                            else
                            {
                                blockIndex = (uint) (first_displayed-10);
                            }
                            
                        }                        else
                        {
                            first_displayed += (y - 10);
                            if (first_displayed <= 10)
                            {
                                blockIndex = 0;
                            }
                            else
                            {
                                blockIndex = (uint)(first_displayed - 10);
                            }
                        }

                        LoadTable(file, (blockIndex));
                        maGridView.Refresh();
                        
                        if (first_displayed > 10)
                        {
                            maGridView.FirstDisplayedScrollingRowIndex = 10;
                        }
                        else
                        {
                            maGridView.FirstDisplayedScrollingRowIndex = first_displayed;
                        }
                      
                    
                    
                }



Résultat, ma Table se recharge bien mais elle n'est pas lue dans le GridView. J'ai une exception System.ArgumentOutOfRangeException qui semble indiquer un problème d'index. Est-ce que j'utilise FirstDisplayedScrollingRowIndex de la mauvaise manière?

5 réponses

Whismeril Messages postés 19034 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 2 mai 2024 656
27 févr. 2014 à 18:07
Bonjour,

pour te répondre il faudrait le code de LoadTable.

Attention à la coloration syntaxique, tu n'as pas choisi le langage C# et une coloration par défaut a été appliquée (je corrige).

Une question cependant, à moins que ta BDD ait plusieurs milliers de lignes, je ne vois pas trop l'intérêt de faire ça.

0
Gorgonzovale Messages postés 4 Date d'inscription mercredi 29 janvier 2014 Statut Membre Dernière intervention 27 février 2014
Modifié par Gorgonzovale le 27/02/2014 à 18:41
Merci de ta réponse et de la correction do coloration.
Pour t'apporter des précisions:
J'avais simplifié mon code précédent mais avant d'appeler LoadTable, j'ouvre un FileStream que je ferme après l'appel.

LoadTable nettoie la DataTable, et reremplie la table au moyen d'un binaryreader et d'une DLL de lecture de nuage de points.

 public void LoadTable(FileStream f, uint start)
            {
                LAS1_1.LASPoint1 pointreader = new LAS1_1.LASPoint1();
                BinaryReader reader = new BinaryReader(f);
                blockTable.Reset();                                      // Reset the points in memory
                pointreader.VersionMajor = hd.VersionMajor;
                pointreader.VersionMinor = hd.VersionMinor;
                LAS1_1.LASUtils.MoveToStartOfPointData(f, start);
                blockTable.Columns.Add("GPS time");
                blockTable.Columns.Add("x");
                                      .
                                      etc
                                      .

                               for (int i = 0; i < (blockSize-1); i++)
                {
                    DataRow blockrow = blockTable.NewRow();
                    
                    LAS1_1.LASUtils.ReadNextPoint(pointreader, reader);
                    byte minor = pointreader.VersionMinor;
                    byte major = pointreader.VersionMajor;
                                
                    blockrow["GPS time"]=pointreader.GPSTime;
                    blockrow["x"] = pointreader.X;
                  // ...etc autres propriétés                  
                    blockTable.Rows.Add(blockrow);

                }

            }


Après l'appel à LoadTable, FirstDisplayedScrollingIndex est à -1,
le Refresh() de ma DataGridView ne fonctionne pas et l'assignation de FirstDisplayedScrollingIndex ne passe pas non plus si j'essaie de la faire avant le Refresh.

Penses-tu que le Binding entre la DataTable et le DataGridView ne supporte pas cette opération de nettoyage remplissage? auquel cas je devrais recreer le lien à chaque fois, ce qui diminue l'intérêt du Binding.

Pour répondre à ta 2eme remarque. C'est mon fichier qui a un nuage de milliers de points avec leurs propriétés. la DataTable sert de buffer pour ne garder en mémoire qu'une taille raisonnable. et charger les données uniquement quand on scrolle, un peu à la UltraEditor.
0
Whismeril Messages postés 19034 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 2 mai 2024 656
27 févr. 2014 à 18:42
Ok, je suppose quelque par tu as spécifié que ta datatable est le DataSource du databindingsource.

Auquel cas essaye un refreshbinding(false) sur ton databindingsource à la fin de loadtable.



Perso je n'irais pas me faire c.... avec une datatable en tampon, j'aurais écrit une classe métier, charge le fichier binaire une fois pour toute dans une List<T> complète et génèrer une liste réduire avec une requête linq sur l'index.

C'est cette liste réduite que j'aurais mis comme DataSource.
0
Gorgonzovale Messages postés 4 Date d'inscription mercredi 29 janvier 2014 Statut Membre Dernière intervention 27 février 2014
27 févr. 2014 à 19:16
Le truc justement, c'est qu'on ne veut à aucun moment charger le fichier binaire en entier.

Donc oui j'ai spécifié que la DataTable est la DataSource de ma BindingSource.

Par contre, j'ai essayé un ResetBindings(false) ou un ResetBindings(true) (j'ai supposé que c'était ça, il n'y a pas de RefreshBinding), j'ai toujours le même problème.

Ma DataTable se charge, le DataGridView.Refresh() n'affiche rien, FirstDisplayedScrollingIndex passe à -1 à la fin de LoadTable et l'assignation de FirstDisplayedScrollingIndex renvoie l'exception ArgumentOutOfRang.

Si tu as une autre idée, je suis preneur.

Merci de ton aide en tous cas.
0
Whismeril Messages postés 19034 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 2 mai 2024 656
27 févr. 2014 à 19:33
ResetBindings(false) , oui c'est ça.

Je suppose que tu as mis un point d'arrêt et que tu constates bien que la datable a été correctement mise à jour?

Peut-etre peux tu essayer, datasource = null, puis datasource = datatable.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Gorgonzovale Messages postés 4 Date d'inscription mercredi 29 janvier 2014 Statut Membre Dernière intervention 27 février 2014
Modifié par Gorgonzovale le 27/02/2014 à 20:54
Oui, c'est ça, mon point d'arrêt me montre une table mise à jour, au bon format, avec les bonnes valeurs.

J'ai essayer ce que tu m'as recommandé,
puis, j'ai même essayé de mettre les dataSource du Binder ET de la GridView à null avant de les remettre à dataTable et dataBinder.
Toujours le même problème.

J'ai même essayé de créer un nouveau Binder qui a pour source la DataTable après mise à jour (pour tester) et de lier ma GridView à ce nouveau Binder (en commentant toute l'histoire d'assignation de FirstDisplayedScrollingIndex).

L'apparence de ma GridView reste comme avant la mise à jour jusqu'à ce que l'exécution sorte du bloc scrollingEvent. Puis à la sortie du bloc, la DataGridView devient grise (seuls les intitulés des colonnes persistent.) Elle n'affiche toujours pas ma DataTable mise à jour.

Il y a bien une tentative de Binding puisque si je mets juste la DataSource de la DataGridView à null, les intitulés des colonnes ne s'affichent même pas. Je ne comprends pas comment ce qui marche à la création de la table peut ne pas marcher lors de la mise à jour puisque je recrée la liaison comme si c'était la première.
0
Whismeril Messages postés 19034 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 2 mai 2024 656
27 févr. 2014 à 20:55
La je sèche.
Je reviens si j'ai une idée.
0
Rejoignez-nous