Pb de rafraichissement de DataGridView

Résolu
Nardo26 Messages postés 37 Date d'inscription samedi 13 janvier 2018 Statut Membre Dernière intervention 1 mars 2021 - Modifié le 21 mai 2019 à 21:39
Nardo26 Messages postés 37 Date d'inscription samedi 13 janvier 2018 Statut Membre Dernière intervention 1 mars 2021 - 22 mai 2019 à 11:41
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

3 réponses

vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié le 22 mai 2019 à 03:26
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

1
Nardo26 Messages postés 37 Date d'inscription samedi 13 janvier 2018 Statut Membre Dernière intervention 1 mars 2021
22 mai 2019 à 08:59
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. :/
0
Nardo26 Messages postés 37 Date d'inscription samedi 13 janvier 2018 Statut Membre Dernière intervention 1 mars 2021
22 mai 2019 à 09:12
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"
0
Nardo26 Messages postés 37 Date d'inscription samedi 13 janvier 2018 Statut Membre Dernière intervention 1 mars 2021
Modifié le 22 mai 2019 à 11:43
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
0
Rejoignez-nous