Pb de rafraichissement de DataGridView [Résolu]

Messages postés
35
Date d'inscription
samedi 13 janvier 2018
Statut
Membre
Dernière intervention
24 mai 2019
-
Bonsoir,

Je rencontre un petit pb : après avoir affecté des DataTables dans des GridView, j'édite le style des lignes en fct de certains critères.
Malheureusement ces modifs n'ont pas l'air d'être prises en considération.
J'ai écrit un petit bout de code pour montrer mon soucis (ce code est complet et peut être exécuté tel quel)...
Il y a 2 choses qui me chiffonne :

1- Dans le Form_load : après avoir affecté la DataTable en source, la méthode count du GridView me renvoie 0. Dans le form_load, les modifs dans les cellules ou sur le style, ne sont pas prises en compte.

2- Une fois que le timer se déclenche, la page active est mise à jour mais pas les autres. Si on clique par exemple sur la page 5 avant le timer, la page 5 est rafraichie MAIS aussi la page 1. Les autres pages restent avec le texte en noir...


Public Class Form1
    Private Clock As New Timer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim TabCtrl As New TabControl With {.Padding = New Point(14, 10), .Dock = DockStyle.Fill}
        AddHandler Clock.Tick, AddressOf ClockEvent

        For i = 1 To 5 ' Création de 5 pages
            Dim p As New TabPage With {.Text = "Page_" + i.ToString}
            With p
                Dim dtaTable As New DataTable("Essai" + i.ToString)
                Dim dtaView As New DataGridView With {.Dock = DockStyle.Fill, .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill}

                For j = 1 To 3
                    dtaTable.Columns.Add("Col_" + j.ToString)
                Next j
                For k = 0 To 15
                    dtaTable.Rows.Add("Nom " + i.ToString + k.ToString, "Prenom " + i.ToString + k.ToString, Now())
                Next k

                dtaView.DataSource = dtaTable

                ' Ceci ne fonctionne pas car dtaView.Rows.Count = 0... pourquoi ?
                ' Par contre, dans la methode du timer, rows.count = 17 dans chaque grid
                For Each row As DataGridViewRow In dtaView.Rows
                    If (row.Index And 1) = 1 Then row.DefaultCellStyle.ForeColor = Color.Red
                Next
                p.Controls.Add(dtaView)
            End With
            TabCtrl.TabPages.Add(p) ' Ajout de la page
        Next
        Me.Controls.Add(TabCtrl) ' Ajout du TabControl dans le form

        ' on lance le timer pour le test
        Clock.Interval = 3000
        Clock.Start()
    End Sub

    Private Sub ClockEvent()
        Dim dtaView As DataGridView
        Dim NbPage As Integer = CType(Me.Controls.Item(0), TabControl).TabPages.Count
        Me.Text = "NbPage:" + NbPage.ToString + " Nb de lignes dans les GridView : "

        ' On passe toutes les lignes de chaque grid en rouge
        For i = 0 To NbPage - 1
            dtaView = CType(Me.Controls.Item(0), TabControl).TabPages(i).Controls(0)
            For Each row As DataGridViewRow In dtaView.Rows
                row.DefaultCellStyle.ForeColor = Color.Red
            Next
            ' le nb de ligne dans les grid est correct alors qu'il ne l'etait pas dans le form_load
            Me.Text += dtaView.Rows.Count.ToString + ","
        Next i
        Clock.Stop()
    End Sub


End Class
Afficher la suite 

3 réponses

Meilleure réponse
Messages postés
1980
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
8 décembre 2019
77
1
Merci
Bonjour
Pour ton premier problème voici le code corrigé pour le Form_Load
Il faut ajouter TabCtrl tout de suite dans la Form sinon tu ne peux point ajouter la DataGridView dans la Page ni ensuite la Page dans TabCtrl car dans ce cas TabCtrl n'est pas présent sur la Form
Et si la DatagridView n'est pas présente sur la Form elle ne se remplit pas avec le DataSource et tu ne peux accéder à son nombre de lignes
Par contre lorsque tu ajoutes TabCtrl à la Form à la ligne 32 de ton premier code tout fonctionne et s'affiche sur la Form mais l'affichage une ligne sur deux en rouge n'a pas pu se faire vu une DataGridview vide et non affichée avant cette ligne 32

 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Dim TabCtrl As New TabControl With {.Padding = New Point(14, 10), .Dock = DockStyle.Fill}
        Me.Controls.Add(TabCtrl) ' Ajout du TabControl dans le form tout de suite
        AddHandler Clock.Tick, AddressOf ClockEvent
        For i = 1 To 5 ' Création de 5 pages
            Dim p As New TabPage With {.Text = "Page_" + i.ToString}
            With p
                Dim dtaTable As New DataTable("Essai" + i.ToString)
                Dim dtaView As New DataGridView With {.Dock = DockStyle.Fill, .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill}
                For j = 1 To 3
                    dtaTable.Columns.Add("Col_" + j.ToString)
                Next j
                For k = 0 To 15
                    dtaTable.Rows.Add("Nom " + i.ToString + k.ToString, "Prenom " + i.ToString + k.ToString, Now())
                Next k
                dtaView.DataSource = dtaTable
                .Controls.Add(dtaView) ' ajout de la DataGridView dans TabPage
                TabCtrl.TabPages.Add(p) ' Ajout de la page dans Tabcontrol
                For Each row As DataGridViewRow In dtaView.Rows
                    If (row.Index And 1) = 1 Then row.DefaultCellStyle.ForeColor = Color.Red
                Next
            End With
        Next
        ' on lance le timer pour le test
        Clock.Interval = 3000
        Clock.Start()

    End Sub


Pour le second souci je ne te comprends pas ! Peux-tu expliquer plus clairement ?
Pour moi les 5 pages sont en rouge

Dire « Merci » 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CodeS SourceS

Codes Sources 200 internautes nous ont dit merci ce mois-ci

Commenter la réponse de vb95
Messages postés
35
Date d'inscription
samedi 13 janvier 2018
Statut
Membre
Dernière intervention
24 mai 2019
0
Merci
Bonjour,

Désolé pour ma réponse longue... ;)

L'ajout du TabControl en début du form load "corrige" en parti les deux problèmes.
Mais je n'en comprend pas la raison.

Si je lance ton code tel quel : je ne passe pas dans la boucle du formLoad puisque la DGV est vide (chose que je ne comprend pas puisqu'il y a eu un Fill juste avant) mais le Timer affecte bien toutes les pages.

"Il faut ajouter TabCtrl tout de suite dans la Form sinon tu ne peux point ajouter la DataGridView dans la Page ni ensuite la Page dans TabCtrl"

La construction des différents objets me parait correcte puisqu'au final, tous les DGV s'affichent avec le contenu des DataTable au moment du fill. Donc L'ajout est bien réalisé.

Chronologiquement je créé une page, je créé une DGV que je modifie puis que j'insère dans la page. Puis cette page je la rajoute à mon TabCtrl. Au final, j'ajoute ce "paquet" d'objets à ma Form. Où se trouve l'erreur dans mon raisonnement ?

Pour avancer, par analogie avec ce que tu me proposes vb95 au sujet du TabControl , j'ai fais de même pour les TabPage et les DataGridView. J'ai inséré ces objets de suite après les avoir instancié et avant de les manipuler.
En faisant cela, pour toutes les TabPages qui sont créées, je passe bien dans la boucle du form_load qui me modifie le style des lignes (c'est déjà un net progrès).
Mais à l'affichage, je n'ai que la 1ere PageTab qui s'affiche correctement.

Ci-joint le code modifié en tenant compte de tes remarques vb95.
Si je ne démarre pas le timer, je me retrouve avec seulement la 1ere TabPage de correcte. Les autres restent noires.

Si je démarre le timer : même punition, seule la 1ere TabPage passe en rouge (et éventuellement la TabPage sélectionnée avant déclenchement) sont mises à jour.

Là, je suis vraiment embrouillé : pourquoi ton code vb95 fonctionne (dans le cadre du timer) et pas le dernier que j'ai fais ?

Public Class Form1
    Private Clock As New Timer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim TabCtrl As New TabControl With {.Padding = New Point(14, 10), .Dock = DockStyle.Fill}
        Me.Controls.Add(TabCtrl) ' Ajout du TabControl dans le form

        For i = 1 To 5 ' Création de 5 pages
            Dim p As New TabPage With {.Text = "Page_" + i.ToString}
            TabCtrl.TabPages.Add(p) ' Ajout de la page
            With p
                Dim dtaTable As New DataTable("Essai" + i.ToString)
                Dim dtaView As New DataGridView With {.Dock = DockStyle.Fill, .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill}
                p.Controls.Add(dtaView)
                dtaView.DataSource = dtaTable

                For j = 1 To 3
                    dtaTable.Columns.Add("Col_" + j.ToString)
                Next j
                For k = 0 To 15
                    dtaTable.Rows.Add("Nom " + i.ToString + k.ToString, "Prenom " + i.ToString + k.ToString, Now())
                Next k

                ' Cette fois-ci, je passe bien dans cette boucle :
                For Each row As DataGridViewRow In dtaView.Rows
                    If (row.Index And 1) = 1 Then row.DefaultCellStyle.ForeColor = Color.Red
                    row.Cells.Item(0).Value = "toto"
                Next

            End With
        Next

        ' on lance le timer pour le test
        AddHandler Clock.Tick, AddressOf ClockEvent
        Clock.Interval = 3000
        Clock.Start()
    End Sub

    Private Sub ClockEvent()
        Dim dtaView As DataGridView
        Dim NbPage As Integer = CType(Me.Controls.Item(0), TabControl).TabPages.Count
        Me.Text = "NbPage:" + NbPage.ToString + " Nb de lignes dans les GridView : "

        ' On passe toutes les lignes de chaque grid en rouge
        For i = 0 To NbPage - 1
            dtaView = CType(Me.Controls.Item(0), TabControl).TabPages(i).Controls(0)
            For Each row As DataGridViewRow In dtaView.Rows
                row.DefaultCellStyle.ForeColor = Color.Red
            Next
            ' le nb de ligne dans les grid est correct alors qu'il ne l'etait pas dans le form_load
            Me.Text += dtaView.Rows.Count.ToString + ","
        Next i
        Clock.Stop()
    End Sub


End Class


Note : si j'inverse les lignes 14 et 15, cela ne fonctionne plus… donc l'ordre parait important mais je n'en saisi pas la logique. :/
Nardo26
Messages postés
35
Date d'inscription
samedi 13 janvier 2018
Statut
Membre
Dernière intervention
24 mai 2019
-
Ce qui est encore plus troublant c'est que si je rajoute cette ligne dans la boucle du Timer, toutes les pages sont bien affectées (mais pas le ForeColor)

 row.Cells.Item(0).Value = "titi"
Commenter la réponse de Nardo26
Messages postés
35
Date d'inscription
samedi 13 janvier 2018
Statut
Membre
Dernière intervention
24 mai 2019
0
Merci
J'ai fini par trouver grâce à vb95 qui m'a mis sur la bonne piste.

il me reste plus qu'à "digérer" ce que cela implique…
(surtout le fait qu'il faut absolument ajouter le TabControl au tout début)

Merci vb95 !

La solution :
Public Class Form1
    Private Clock As New Timer


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim TabCtrl As New TabControl With {.Padding = New Point(14, 10), .Dock = DockStyle.Fill}
        Me.Controls.Add(TabCtrl) ' Ajout du TabControl dans le form

        For i As Integer = 1 To 5 ' Création de 5 pages
            ' Cet ordre est très important
            Dim dtaView As DataGridView = New DataGridView With {.Dock = DockStyle.Fill, .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill}
            Dim tPage As New TabPage With {.Text = "Page_" + i.ToString}
            tPage.Controls.Add(dtaView)
            TabCtrl.TabPages.Add(tPage) ' Ajout de la page

            Dim dtaTable As DataTable = New DataTable("Essai" + i.ToString)
            For j As Integer = 1 To 3
                dtaTable.Columns.Add("Col_" + j.ToString)
            Next j
            For k As Integer = 0 To 15
                dtaTable.Rows.Add("Nom " + i.ToString + k.ToString, "Prenom " + i.ToString + k.ToString, Now())
            Next k

            With dtaView
                .DataSource = dtaTable
                .SelectionMode = DataGridViewSelectionMode.FullRowSelect
                .AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(192, 255, 192) ' pour le fun 
            End With

            For Each row As DataGridViewRow In dtaView.Rows
                If (row.Index Mod 3) = 0 Then row.DefaultCellStyle.ForeColor = Color.Red
                row.Cells.Item(0).Value = "toto"
            Next
            dtaTable = Nothing
            dtaView = Nothing
        Next

        ' on lance le timer pour le test
        AddHandler Clock.Tick, AddressOf ClockEvent
        Clock.Interval = 5000
        Clock.Start()
    End Sub

    Private Sub ClockEvent()
        For i As Integer = 0 To CType(Me.Controls(0), TabControl).TabPages.Count - 1
            RafrDGV(i)
        Next
        Clock.Stop()
    End Sub

    Private Sub RafrDGV(Optional ByVal Id As Integer = -1)
        Dim dtaView As DataGridView

        With CType(Me.Controls(0), TabControl) ' on pointe sur le tabControl
            If Id = -1 Then Id = .SelectedIndex
            dtaView = .TabPages(Id).Controls(0)
            For Each row As DataGridViewRow In dtaView.Rows
                If (row.Index Mod 3) = 0 Then ' un test quelconque pour l'exemple
                    row.DefaultCellStyle.ForeColor = Color.Red
                    row.Cells.Item(0).Value = (Id + 1).ToString + "_titi"
                End If
            Next
        End With
    End Sub

End Class
Commenter la réponse de Nardo26