VB.net | CheckedListBox

Résolu
Bonjour,

Je suis actuellement en Stage et je réalise une application en Visual Basic sous Visual Studio 2008.

Je souhaiterais remplir une CheckedListBox à l'aide d'une base de donnée, jusque là tout va bien, je prend les valeurs disponible dans une Table "LesDates", mais j'aimerais aussi que certaines données soit cochées en fonction des valeurs d'une autre table.
J'y arrive plus en moins avec ce code, mais je n'ai actuellement qu'une valeur de cochée.
Vous pouvez voir les requêtes que j'ai effectué dans le code, tout fonctionne avec des DataReader

    Private Sub LB_CharResEnf_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LB_CharResEnf.SelectedIndexChanged
        CLB_DatesReserv.Items.Clear()
        Dim moncode() As String
        Dim i As Integer, j As Integer
        moncode = Split(LB_CharResEnf.SelectedItem, " ")
        Dim sqlCnx As New System.Data.Odbc.OdbcConnection(My.Settings.CS_CantineBDD)
        Dim uneleve As New System.Data.Odbc.OdbcCommand("SELECT codeeleve,nome,prenome,ecolee,classee,droitphoto,anneeencour FROM eleves WHERE codeeleve = " & moncode(0) & "", sqlCnx)
        Dim Nbdates As New System.Data.Odbc.OdbcCommand("SELECT COUNT(datedispo) FROM lesdates", sqlCnx)
        Dim mesdates As New System.Data.Odbc.OdbcCommand("SELECT datedispo FROM lesdates", sqlCnx)
        Dim mesdatesreservees As New System.Data.Odbc.OdbcCommand("SELECT jourreserv FROM reservation WHERE codeelever = " & moncode(0) & "", sqlCnx)
        Dim myreader As Odbc.OdbcDataReader, myreader2 As Odbc.OdbcDataReader, myreader3 As Odbc.OdbcDataReader

        sqlCnx.Open()
        myreader = uneleve.ExecuteReader()
        myreader2 = mesdates.ExecuteReader()
        myreader3 = mesdatesreservees.ExecuteReader()

        myreader.Read()
        TB_NomE.Text = myreader.GetString(1).ToString
        TB_PrenomE.Text = myreader.GetString(2).ToString
        TB_EcoleE.Text = myreader.GetString(3).ToString
        TB_ClasseE.Text = myreader.GetString(4).ToString

        For i = 0 To Nbdates.ExecuteScalar - 1
            myreader2.Read()
            CLB_DatesReserv.Items.Add(myreader2.GetDate(0))

            For j = 0 To CLB_DatesReserv.Items.Count
                myreader3.Read()
                Try
                    If myreader2.GetDate(0) = myreader3.GetDate(0) Then
                        CLB_DatesReserv.SetItemChecked(j, True)
                    End If
                Catch
                    'Rien
                End Try

            Next
        Next
        sqlCnx.Close()

    End Sub


En espérant que vous puissiez m'aider, merci d'avance

Cordialement,

Xineroks

11 réponses

Résumé de la discussion

Un stagiaire tente de remplir une CheckedListBox avec des dates issues d'une table et de cocher celles correspondant à des valeurs d'une autre table, dans une application Visual Basic sous Visual Studio 2008. Plusieurs réponses signalent un décalage entre boucles et DataReader, recommandant de séparer les boucles et les lectures, et d'utiliser Try/Catch pour éviter les erreurs lors de la comparaison des dates. En pratique, les échanges recommandent de séparer la phase de remplissage des dates et celle de test des réservations, puis d'ajouter des contrôles d'échec et, éventuellement, d'utiliser Contains pour valider l'index. Certaines propositions avancent aussi d'examiner les indices i et j afin d'éviter de cocher le mauvais élément lorsque le nombre d'enregistrements diffère entre les tables.

Bobot (l’IA à votre service)
  1. Contributeur
    Bonjour,
    A première vue, Je ne vois rien qui cloche sauf..
    ' Set flag to true to know when this code is being executed. Used in the ItemCheck  
        ' event handler.  
        insideCheckEveryOther = True 
            ..... 
        insideCheckEveryOther = False 
    

    Tu dis.
    Edit: Dans ton Catch.. met un stop
    Si tu te cognes à un pot et que ça sonne creux, c'est pas forcément le pot qui est vide. ;-)(Confucius)
    NOTE : Je ne répond pas aux MP pour les questions techniques.
    1. Le soucis c'est que j'utilise l'événement SelectedIndexChanged, donc je ne peux pas ajouter
          insideCheckEveryOther = True 
              ..... 
          insideCheckEveryOther = False


      Du moins je crois, m'enfin j'aimerais garder cet événement car ensuite je dois faire une requête qui ajoutera dans la base une date.

      Edit : si je ne met pas de try catch, j'ai l'erreur comme quoi je n'ai pas de valeur dans mon reader3, et si je met un stop, bah ça stop ^^'
      J'aimerai que l'appli tourne, même si erreur.
      Je crois que ça vient de mon reader3 en fait
      1. Contributeur
        C'est bien ça, je viens de tester une ListB avec quelque lignes et tes commandes fonctionnent parfaitement.
        Mais pour voir si toute ta table reader3 est défectueuse tu devrais tester plusieurs passages.
        Si tu connais oublie ceci..taper F8 pour continuer après un stop.
        Mais apparemment ( tu dis qu'il y a une seule date cochée) c'est toute la table qui va pas.
        Edit : Je pense à une chose ?
        Reader2 et Reader3 ont le même nombre d'enregistrements?
        quand ça plante regarde les valeurs de J et i
      2. Le nombre d'enregistrement est différent oui, mais le nombre d'enregistrement qu'on manipule dans la boucle J est forcément inférieur ou égal au nombre de valeur dans la boucle I. Donc, je pense qu'on parcourt bien toute les valeurs.
        Car pour remplir ma 2ème table on s'inspire des valeurs de la première.
      3. Contributeur
        Bonjour,
        Je ne connais pas ton niveau,
        Tu connais BIEN VB pour debuger tu veux une explication ou ce n'est pas nécessaire ?
      4. Oui je connais assez bien , ça doit faire un 1 que je pratique. :)
        Pour l'application ce n'est pas nécessaire pour le moment ( du moins j'espère )
        Je vais essayer de séparer mes 2 boucles maintenant afin de voir si ça change quelque chose.
      5. Contributeur
        OK, je reste en attente pour la matinée.
    2. Contributeur
      Mais si, C'est pour éviter que l'évènement se rappel, (récursive)
      Tu est certain de tes données ?
      If myreader2.GetDate(0) = myreader3.GetDate(0) Then

      Et qu'il y en à plusieurs qui sont égales
      Met aussi un stop en dessous de cette ligne, tu verras ainsi combien de fois il s'arrête.
      EDIT : Et comme tu met la liste Clear au début de la sub...
      Humm.. oui, c'est pas la même :-)
      Si tu te cognes à un pot et que ça sonne creux, c'est pas forcément le pot qui est vide. ;-)(Confucius)
      NOTE : Je ne répond pas aux MP pour les questions techniques.
      1. Oui, mes données sont correctes.
        Car justement une donnée est cochée
        en gros je passe dans i avec la date 15/12/2012, venant de myreader2 par exemple,
        je regarde si dans myreader3 si j'ai la date qui est égale, parmi toutes les dates de myreader3 donc, je tombe forcément dessus. J'ai mis en sorte que 3 enregistrements soit identique sur la date par rapport à l'autre table donc ça va.

        Sinon, je ne connaissais pas "insideCheckEveryOther = True", alors je ne sais pas où le placer ( j'ai tenté partout ^^" )
        1. Contributeur
          Bon, Oublie mon poste précédant je n'avais pas bien lu.
          Je pense que tu devrais séparer tes deux boucles.
          La première remplir la liste et la deuxième tester les dates.
          Mon avis le problème vient de là,
          Explique un peu, tout les indices sont à zéro ? je ne comprend pas.

          Si tu te cognes à un pot et que ça sonne creux, c'est pas forcément le pot qui est vide. ;-)(Confucius)
          NOTE : Je ne répond pas aux MP pour les questions techniques.
          1. Les indices c'est pour récupérer la première colonne de ma requête
        2. J'avais tester tout à l'heure mais sans résultat car je n'avais pas tester le try catch. Je testerai ça demain au plus tôt afin de régler ce problème qui me gène vraiment.
          Si d'autres idées viennent, je serais ravi de les lire.

          Bonne soirée,

          Xineroks
          1. Solution :

                    For i = 0 To Nbdates.ExecuteScalar - 1
                        myreader2.Read()
                        CLB_DatesReserv.Items.Add(myreader2.GetDate(0))
                    Next
                    For j = 0 To CLB_DatesReserv.Items.Count
                        Try
                            myreader3.Read()
                            If CLB_DatesReserv.Items.Contains(myreader3.GetDate(0)) Then
                                CLB_DatesReserv.SetItemChecked(CLB_DatesReserv.Items.IndexOf(myreader3.GetDate(0)), True)
                            End If
                        Catch
                        End Try
                    Next


            On parcourt la première boucle pour insérer les données. La Deuxième boucle pour comparer les données. Si une valeur est correspond aux 2 tables alors on recupère l'index de la CLB, pour la mettre à True.

            Merci à lermite222 pour son aide apportée pour résoudre mon problème.
            1. Contributeur
              Essaye un peu ça..
                      For j = 0 To CLB_DatesReserv.Items.Count
                          For i = 0 To Nbdates.ExecuteScalar - 1
                              Try
                                  myreader3.Read()
                                  If CLB_DatesReserv.Items(j) = (myreader3.GetDate(0)) Then
                                      CLB_DatesReserv.SetItemChecked(j, True)
                                      Exit For
                                  End If
                              Catch
                              End Try
                          Next
                      Next

              1. Si je fais ça, je ne remplis pas avant ma CLB. même en ajoutant

                            myreader2.Read()
                            CLB_DatesReserv.Items.Add(myreader2.GetDate(0))

                dans entre les 2 for, j'aurai qu'une seule donnée. C'est pourquoi je vais opter pour la solution que j'ai mis ^^

                Merci beaucoup encore d'avoir prit un peu de ton temps pour m'aider :)
              2. Contributeur
                Mais il faut garder la première boucle !!!
                Et c'est pas bien de se décourager ainsi.
                Regarde mon dernier poste.
              3. Du coup ça travaille beaucoup plus sur les instructions non ? 3 boucles, au lieu de 2 ? Je me décourage pas ^^, j'adore ce que je fais. Je pourrais coder pendant 42H/jour
            2. Contributeur
              Correction:
              Je pense que tu peu garder la boucle comme toi tu l'a montrer.
              Pour le décalage il faudrait réinitialiser la table Reader3 au début mais en net je sais pas la commande à appliquer et ça fait longtemps que je n'ai plus fait de DB en VB
              Si tu te cognes à un pot et que ça sonne creux, c'est pas forcément le pot qui est vide. ;-)(Confucius)
              NOTE : Je ne répond pas aux MP pour les questions techniques.
              1. Yup ça marche nikel ;)
              2. Contributeur
                Content que ça marche, il à fallu longtemps avant que la cafetière ne soit chaude mais y a un bail que j'ai travaillé sur ce type de BD et en plus c'était en VB6,
                A+
            3. Ca fonctionnait, ça ne fonctionne plus o_O

                  For i = 0 To Nbdates.ExecuteScalar - 1  
                          myreader2.Read()  
                          CLB_DatesReserv.Items.Add(myreader2.GetString(0))  
                      Next  
                      myreader2.Close()  
                      For j = 0 To CLB_DatesReserv.Items.Count  
              
                          Try  
                              myreader3.Read()  
                              If CLB_DatesReserv.Items.Contains(myreader3.GetString(0)) Then  
                                  CLB_DatesReserv.SetItemChecked(CLB_DatesReserv.Items.IndexOf(myreader3.GetString(0)), True)  
                              End If  
                          Catch  
                          End Try  
                      Next


              Je comprend pas pourquoi, ça ne coche plus rien alors que le code est le même

              Une fois après avoir remarqué que ça ne fonctionnait plus j'ai remplacer getDate() par getString(). Ca ne pose pas de soucis normalement, et c'est pour des soucis de simplicité dans une autre requête.

              EDIT : En fait ça ne fonctionne plus quand j'ajoute ce code, qui permet d'ajoute dans la base une date pour un reservation si c'est coché, et ça supprime la reservation si c'est décoché

              avec ce code

                  Private Sub CLB_DatesReserv_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CLB_DatesReserv.ItemCheck
                      Dim moncode() As String
                      moncode = Split(LB_CharResEnf.SelectedItem, " ")
                      Dim sqlCnx As New System.Data.Odbc.OdbcConnection(My.Settings.CS_CantineBDD)
                      Dim maxReserv As New System.Data.Odbc.OdbcCommand("SELECT MAX(codereservation) FROM reservation", sqlCnx)
                      Dim selectParent As New System.Data.Odbc.OdbcCommand("SELECT codeparenta FROM avoir, parents, eleves WHERE eleves.codeeleve=avoir.codeelevea AND avoir.codeparenta=parents.codeparent AND codeelevea = " & moncode(0) & "", sqlCnx)
                      Dim ajoutDate As New System.Data.Odbc.OdbcCommand()
                      Dim suppDate As New System.Data.Odbc.OdbcCommand()
              
                      sqlCnx.Open()
                      If CLB_DatesReserv.GetItemChecked(CLB_DatesReserv.Items.IndexOf(CLB_DatesReserv.SelectedItem)) = False Then
                          ajoutDate.Connection() = sqlCnx
                          ajoutDate.CommandText() = "INSERT INTO reservation VALUES('" & maxReserv.ExecuteScalar + 1 & "','RR','N','" & moncode(0) & "','" & selectParent.ExecuteScalar & "','" & CLB_DatesReserv.SelectedItem & "')"
                          ajoutDate.ExecuteNonQuery()
                      Else
                          suppDate.Connection() = sqlCnx
                          suppDate.CommandText() = "DELETE FROM reservation WHERE codeelever = " & moncode(0) & " AND jourreserv = " & CLB_DatesReserv.SelectedItem & ""
                          suppDate.ExecuteNonQuery()
                      End If
              
                      sqlCnx.Close()
                  End Sub
              1. Sauriez vous peut être me dire si l'evenement est incorrect ou bien incompatible et lequel devrai-je utiliser lorsque je veux qu'une requete d'ajout ou de suppréssion se fasse lorsque que le checked change
            4. Contributeur
              C'est ici que ma remarque est importante.
              Mais comme tu travaille sur la ListBox dans un autre évènement ces commande ne fonctionneront pas.
              Pour remédier à ce problème j'emploi un variable boolean public.
              Public NoAction as Boolean = False
              Avant d'attaquer les modif dans la liste je la met à True
              quand c'est terminer pas oublier de la remettre à False
              Et dans l'événement change je met la ligne en tout début
              If Noaction then exit sub
              Bon, ça régler je me demande si tu peu ouvrir deux même table en même temps, quel est le type d'erreur ?
              Essaye le system avec NoAction et refaire une boucle à part en retestant les items de la ListB

              Si tu te cognes à un pot et que ça sonne creux, c'est pas forcément le pot qui est vide. ;-)(Confucius)
              NOTE : Je ne répond pas aux MP pour les questions techniques.
              1. Merci !
                Wow, j'aurais jamais trouvé tout seul !
                Ca fonctionne à merveille avec cette variable, mais par contre ça veut dire que les 2 événements tournent en même temps ?
              2. Contributeur
                NON, mais quand tu modifie un item de la listebox que se soit en cliquant dessus ou par code l'évènement CHANGE (les autre aussi d'ailleurs) est généré CQFD.
                T'a encore appris quaiqchose aujourd'hui :-))
                A+