1. #1
    Membre habitué
    Profil pro
    Inscrit en
    août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : août 2005
    Messages : 346
    Points : 127
    Points
    127

    Par défaut Comment faire un Listbox qui contient des objets<T> contenus dans une List<T> ?

    Bonjour,

    J'ai un événement qui ajoute régulièrement un nouvel objet à une List<T>.

    J'aimerai refléter le contenu de cette List<T> dans un contrôle liste.

    Pour ça, j'ai essayé d'ajouter les éléments dans une Listbox mais je n'y arrive pas (problème d'"inter thread" quand j'utilise .Items.Add()).

    Quelle est la bonne méthode ? Je débute en C#... Donc si vous pouvez être assez explicite ou me donner un tuto clair là dessus, ce geste sera bienvenu :-)

    Bonne journée

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2007
    Messages : 547
    Points : 625
    Points
    625

    Par défaut

    Salut,

    ce n'est pas un probleme de liste (du moins pour le moment), tu essayes d'ajouter des items à partir d'un autre thread, d'ou le plantage cross-threads access blabla.

    Utilises tu des timers, un backgroundworker ou simplement un autre thread ?

  3. #3
    Membre actif Avatar de g_tarik0010
    Homme Profil pro
    Développeur Web
    Inscrit en
    mai 2006
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : mai 2006
    Messages : 186
    Points : 284
    Points
    284

    Par défaut

    Une piste pour chercher :

    Les delegués et les methodes BeginInvoke() et Invoke de ton composant List

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    février 2003
    Messages
    311
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : Belgique

    Informations forums :
    Inscription : février 2003
    Messages : 311
    Points : 337
    Points
    337

    Par défaut

    Je vote pour le backgoundworker aussi...

    C'est l'outil idéal pour gérer les soucis de thread quand on utilise les Windows Form

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : août 2005
    Messages : 346
    Points : 127
    Points
    127

    Par défaut

    Euh....

    Comme je commence, je ne connais pas encore tout ça mais j'utilise des délégués, pas de timer (que je sache).

    Voilà ce que fait mon programme:

    - il écoute sur un port série (System.IO.Ports)
    - lorsqu'une trame intéressante arrive, il crée un événement.
    - cet événement est reçu par la classe de ma form1, qui contient le ListBox. Je récupère l'objet fourni par l'événement dans une collection. Puis j'essaie d'ajouter l'objet dans ma ListBox... et là ça me sort ce problème de thread :
    "Opération inter-threads non valide : le contrôle 'listBox' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé."

    J'utilise donc à 2 reprises des délégués : pour le DataReceiver de SerialPort et pour créer l'événement lorsqu'une trame complète est reçue.

    Effectivement, l'écoute du port série se fait par un autre thread (je suppose). Mais je récupère pourtant l'objet dans la classe de ma feuille avant de l'ajouter à ma listbox...

    Voilà le code correspondant à la réception de l'événement dans la Form1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Reçoit les événements TrameRecue
            public void ReceptionTrame(EventArgs e) {
                NouvelleTrameEventArgs trame = e as NouvelleTrameEventArgs; 
                if (trame != null)
                {
                    messageLabel.Text = "Nouvelle trame reçue :" + trame.trame.ToString();
                    SystemSounds.Beep.Play();
                    m_listeTrames.Add(trame.trame);
                    listBox.Items.Add(trame.trame.ToString()); // Erreur ici (inter-thread)
                }
            }
    Mon erreur doit être bête puisque je ne parviens même pas à ajouter une simple chaîne de caractères avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    listBox.Items.Add("test"); // Meme erreur
     
    string test = "test";
    listBox.Items.Add(test); // Meme erreur
    Cela aide-t-il à comprendre mon souci ?

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    février 2003
    Messages
    311
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : Belgique

    Informations forums :
    Inscription : février 2003
    Messages : 311
    Points : 337
    Points
    337

    Par défaut

    J'ai lu en diagonale, mais je pense qu'il faut que tu intègres ton écoute sur le port série dans un backgroundworker, ce qui te permettra de modifier ta fenêtre facilement après.

    Jette un oeil ici:

    http://msdn.microsoft.com/en-us/libr...undworker.aspx

    En espérant que ça t'aide

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : août 2005
    Messages : 346
    Points : 127
    Points
    127

    Par défaut

    Merci zoubidaman, après avoir lu quelques articles liés au BackgroundWorker, je pense aussi que c'est ça mais je n'ai pas trouvé de bon tuto là dessus.

    Après avoir lu la page d'MSDN sur le backgroundWorker, il semble que ça corresponde bien à mon cas

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : août 2005
    Messages : 346
    Points : 127
    Points
    127

    Par défaut J'ai finalement utilisé BeginInvoke()

    Finalement, j'ai utilisé BeginInvoke() de mon ListBox comme me le conseillait g_tarik0010.

    Ca me semblait moins lourd que faire un BackGroundWorker.

    Etant donné que je stocke l'objet envoyé par l'événement dans mon ListBox, je ne devrai plus avoir de problème avec cet objet lorsque je le récupérerai de mon ListBox, je me trompe ?

    Si c'est exact, cette solution me suffit pour ce que je veux faire...

    Merci encore pour vos réponses.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    // Reçoit les événements NouvelleTrameEventArgs
            // Note : ReceptionTrame() est appelé par le processus qui crée l'événement (soit un autre thread que celui de la Form)
            // ReceptionTrame() n'a donc pas directement accès aux contrôles de la form.
            public void ReceptionTrame(EventArgs e) {
     
                NouvelleTrameEventArgs trame = e as NouvelleTrameEventArgs; // Tente de convertir e en NouvelleTrameEventArgs
                if (trame != null)
                {
                    DefTrame nouvelleTrame = trame.Trame;
                    messageLabel.Text = "Nouvelle trame reçue :" + nouvelleTrame.ToString();
                    SystemSounds.Beep.Play();
                    listBox_Trame.BeginInvoke(new DelegateListBox_Trame(DelegateAddItem_Trame), nouvelleTrame);
     
                }
            }
     
    // Délégué pour appeler DelegateAddItem_Trame de façon thread-safe
            private delegate void DelegateListBox_Trame(DefTrame element);
     
            // Méthode appelée par un délégué pour opération thread-safe sur listbox_Trame
            private void DelegateAddItem_Trame(DefTrame element)
            {
                listBox_Trame.Items.Add(element);
            }

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : août 2005
    Messages : 346
    Points : 127
    Points
    127

    Par défaut Façon simple de vérifier si ma listBox contient déjà un objet avant de l'ajouter ?

    Une nouvelle question qui est la suite directe de la solution précédente :

    y a t il un moyen de vérifier que ma listbox contient un objet avant de lui ajouter ce dernier ?

    J'ai essayé en vain un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (! listBox_Trame.Items.Contains(nouvelleTrame)) 
    listBox_Trame.BeginInvoke(new DelegateListBox_Trame(DelegateAddItem_Trame), nouvelleTrame);
    Ca retourne toujours false.

    S'il faut faire une boucle pour le vérifier, je ferai ça, mais je suppose qu'il y a plus joli à faire, non ?

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    février 2003
    Messages
    311
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : Belgique

    Informations forums :
    Inscription : février 2003
    Messages : 311
    Points : 337
    Points
    337

    Par défaut

    Et un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(! listBox_Trame.Items.Contains(nouvelleTrame.ToString()))
    ??

    Ca a l'air de fonctionner chez moi ça...

Discussions similaires

  1. [Débutant] Drag Drop entre deux ListBox qui contiennent des objets
    Par shaun_the_sheep dans le forum Windows Forms
    Réponses: 2
    Dernier message: 12/10/2012, 18h15
  2. Comment faire pour que le focus soit à la fin d'un texte dans une textbox ?
    Par gryffondor8392 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 24/02/2011, 22h07
  3. Réponses: 3
    Dernier message: 08/10/2010, 13h42
  4. Réponses: 4
    Dernier message: 25/04/2007, 17h23
  5. comment fermer un site qui contient des framesets
    Par zana74 dans le forum Syntaxe
    Réponses: 6
    Dernier message: 20/08/2006, 17h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo