none
La modification du DataSource ne modifie pas le contenu du listbox ??? RRS feed

  • Question

  • Bonjour,

    C'est sans doute évident, mais quelquechose m'échappe et je n'arrive pas à modifier le contenu de mon listbox en modifiant directement le DataSource.

    Voici la déclaration de ma liste et de ma StringCollection qui me sert de DataSource:

    'DECLARATION
      Public MotsDispos As System.Collections.Specialized.StringCollection
      Public lvwMotsDispos As System.Windows.Forms.ListBox
    
    'RENSEIGNEMENT DU STRINGCOLLECTION
        MotsDispos = New System.Collections.Specialized.StringCollection
        MotsDispos.AddRange(System.IO.File.ReadAllLines("listedemot.txt"))
    
    'ASSOCIATION AU LISTBOX
        Me.lvwMotsDispos = New System.Windows.Forms.ListBox
        Me.lvwMotsDispos.DataSource = MotsDispos
        Me.Controls.Add(Me.lvwMotsDispos)
    

     

    Ensuite je modifie ma collection "MotsDispos", mais ça ne se répercute pas sur la listbox:

        Me.lvwMotsDispos.BeginUpdate()
        MotsDispos.Remove("toto")
        Me.lvwMotsDispos.EndUpdate()
    

     

    J'ai essayé différentes variantes sans succès. Je n'arrive pas à savoir comment utiliser DataBindings...

    POUVEZ-VOUS M'AIDER SVP ???

    Merci...


    Projet volumineux en cours de migration de Vb6 à VbNet2008 Visual Studio 2008 - VbNET/Vb6(COM)
    lundi 19 avril 2010 14:22

Réponses

  • Bonjour Golard,

    Ton souci semble provenir de ta sources de données. Si tu veux avoir un binding prenant en charge les modification de ta liste il faudrait utilier une BindingList(Of String) ne lieu et place de la StringCollection.

    La seule grand différence avec ton code serras donc la déclaration et le remplissage de la liste :

    'DECLARATION
     Public MotsDispos As System.ComponentModel.BindingList(Of String)
     Public lvwMotsDispos As System.Windows.Forms.ListBox
    
    'RENSEIGNEMENT DU STRINGCOLLECTION
      MotsDispos = New System.ComponentModel.BindingList(Of String)()
      
    For Each mot As String In System.IO.File.ReadAllLines("listedemot.txt")
    
    MotsDispos.Add(mot)
    
    Next


    Jérémy Jeanson MCP http://blogs.codes-sources.com/JeremyJeanson/ (French or English Spoken)
    • Marqué comme réponse Golard lundi 26 avril 2010 07:05
    lundi 19 avril 2010 15:38
  • Bonjour,

    Il faut réinitializer la listBox.DataSource pour voir le mise à jour

        MotsDispos.Remove("toto")
        Me.lvwMotsDispos.DataSource = Nothing
        Me.lvwMotsDispos.DataSource = MotsDispos
    • Marqué comme réponse Golard lundi 26 avril 2010 07:05
    lundi 19 avril 2010 19:09
  • Bonjour tout le monde,

    Attention le changement de DataSource en passant une source vide puis une souce mise à jour est une astuce pour contourner le souci. Cette astuce a l'inconvénient de mettre entièrement à jour le control. On perd donc le context dans lequel est le control (item sélectionné, text en surbrillance ou toute autre chose du genre. En plus on déclenche un affichage à vide, donc un risque de scintillement de l'interface graphique (très prononcée sur les pc un peu dépassés).

    D'où l'interret d'un DataBinding et d'une liste typée pour le DataBinding (BindingList).  En plus cela rend inutile les appels aux méthodes BeginUpdate et EndUpdate.

    Petit plus la philosophie est proche du Binding WPF, donc si un jour vous envisagez le passage à WPF, vous serrez déjà un peu plus préparés  ;)


    Jérémy Jeanson MCP http://blogs.codes-sources.com/JeremyJeanson/ (French or English Spoken)
    • Marqué comme réponse Golard lundi 26 avril 2010 07:06
    mardi 20 avril 2010 07:31

Toutes les réponses

  • Bonjour Golard,

    Ton souci semble provenir de ta sources de données. Si tu veux avoir un binding prenant en charge les modification de ta liste il faudrait utilier une BindingList(Of String) ne lieu et place de la StringCollection.

    La seule grand différence avec ton code serras donc la déclaration et le remplissage de la liste :

    'DECLARATION
     Public MotsDispos As System.ComponentModel.BindingList(Of String)
     Public lvwMotsDispos As System.Windows.Forms.ListBox
    
    'RENSEIGNEMENT DU STRINGCOLLECTION
      MotsDispos = New System.ComponentModel.BindingList(Of String)()
      
    For Each mot As String In System.IO.File.ReadAllLines("listedemot.txt")
    
    MotsDispos.Add(mot)
    
    Next


    Jérémy Jeanson MCP http://blogs.codes-sources.com/JeremyJeanson/ (French or English Spoken)
    • Marqué comme réponse Golard lundi 26 avril 2010 07:05
    lundi 19 avril 2010 15:38
  • Bonjour,

    Il faut réinitializer la listBox.DataSource pour voir le mise à jour

        MotsDispos.Remove("toto")
        Me.lvwMotsDispos.DataSource = Nothing
        Me.lvwMotsDispos.DataSource = MotsDispos
    • Marqué comme réponse Golard lundi 26 avril 2010 07:05
    lundi 19 avril 2010 19:09
  • Bonjour tout le monde,

    Attention le changement de DataSource en passant une source vide puis une souce mise à jour est une astuce pour contourner le souci. Cette astuce a l'inconvénient de mettre entièrement à jour le control. On perd donc le context dans lequel est le control (item sélectionné, text en surbrillance ou toute autre chose du genre. En plus on déclenche un affichage à vide, donc un risque de scintillement de l'interface graphique (très prononcée sur les pc un peu dépassés).

    D'où l'interret d'un DataBinding et d'une liste typée pour le DataBinding (BindingList).  En plus cela rend inutile les appels aux méthodes BeginUpdate et EndUpdate.

    Petit plus la philosophie est proche du Binding WPF, donc si un jour vous envisagez le passage à WPF, vous serrez déjà un peu plus préparés  ;)


    Jérémy Jeanson MCP http://blogs.codes-sources.com/JeremyJeanson/ (French or English Spoken)
    • Marqué comme réponse Golard lundi 26 avril 2010 07:06
    mardi 20 avril 2010 07:31
  • Bonjour,

    en plus de la solution proposée par Jérémy, il est également possible de rafraichir le CurrencyManager associé à la ListBox :

    CType(Me.lvwMotsDispos.BindingContext(Me.lvwMotsDispos.DataSource), CurrencyManager).Refresh()
    Cordialement

     

     

    mardi 20 avril 2010 08:14
    Modérateur
  • Il s'agit tout simplement d'effectuer un reset de datasource avant de lui réassigné le StringCollection MotsDispos, puisque l'update de contenu de Listbox s'effectue dans une fonction séparé à celle ou il y a le chargement initiale.

     

    J'ai testé la solution que j'ai proposé avant de la poster et elle fonctionne parfaitement.

     

     

    mardi 20 avril 2010 10:08
  • Bonjour Hammadi,

    Oui bien entendu, ta solution fonctionne. Je ne me permettais pas de la remettre en cause, le souci c'est qu'elle a des nombreuses conséquences sur le comportement du control dont on affect la DataSource et sur son environnement .

    Dans le contexte d'un DataBinding, seul les éléments mis à jour sont affectés. On ne touche donc qu'à ce qui change. Il n'y a aucun effet de bords, contrairement à une affectation du DataSource des que l'on change une donnée dans la source.

    Sur un ListBox les effets de bords ne sont pas trop visible de premier abord, tant qu'il n'y a pas d'autre contrôles bindés sur la Listbox. Et c'est là que les choses coincent. Dans un sénario maitre détail, si le listbox sert de maitre pour déterminé l'item dont on voit le détail, dès que l'on fait l'update du datasource on risque le déclenchement d'une ou plusieurs opérations sur le détail ...

    Plus le scénario de binding est important et plus les effets de bords seront nombreux :(


    Jérémy Jeanson MCP http://blogs.codes-sources.com/JeremyJeanson/ (French or English Spoken)
    mardi 20 avril 2010 10:20
  • Bonjour,

     

    Je vous remercie à tous pour les réponses.

     

    Golard, je vous prie de confirmer si ces solutions vous ont été utiles.

     

    Cordialement,

    Alex


    Appel à contribution ! http://social.msdn.microsoft.com/Forums/fr-FR/vbasicfr/thread/bd974e0e-5519-4122-b8fc-3b998207c34f
    mardi 20 avril 2010 12:32
  • Bonjour à tous et merci pour vos réponses,

    Bien sur Alex que ces réponses me sont très utiles.

    Suite aux 2 premières réponses de Jeanson Jérémy et Hammadi Dali, j'ai essayé la méthode de Hammadi Dali car elle me permettait une solution rapide à mon code existant pour pouvoir fournir un exécutable fonctionnel. Je l'avais déjà essayé sans succès, mais cette fois ça a fonctionné en l'utilisant conjointement aux BeginUpdate et EndUpdate.

    Ensuite j'ai lu avec beaucoup d'attention les arguments de Jeanson Jérémy, et j'envisage très sèrieusement d'améliorer mon programme en utilisant des BindingList of String plutôt que mes StringCollection. J'ai noté l'avantage d'un meilleur comportement du formulaire + une ouverture sur le WPF qui ne me laisse pas insensible... N'y-a-t'il pas aussi une plus grande rapidité de traitement ?

    Techniquement, si j'utilise la syntaxe des BindingList of String proposée par Jeanson Jérémy, je n'ai à renseigner NI le DataSource, NI le DataBinding... Pouvez-vous me confirmer ?

    Concernant la proposition de nikho, est-ce une alternative permettant d'utiliser malgré tout le DataSource sans les inconvénients énoncés par Jeanson ?

    Je vous remercie si vous pouvez répondre à ces quelques questions supplémentaires, et je viendrai "Marquer comme réponse" dés que j'aurai testé le BindingList.

    Cordialement,

    A très bientôt.


    Projet volumineux en cours de migration de Vb6 à VbNet2008 Visual Studio 2008 - VbNET/Vb6(COM)
    mercredi 21 avril 2010 07:21
  • Bonjour Golard

    -> + une ouverture sur le WPF qui ne me laisse pas insensible

    Ouverture... disons plutôt approche similaire car cette liste n'est pas prise en charge comme l'observablecollection en WPF ;)

    Pour les performances : désolé, mais non la bindingliste n'apporte rien par contre les changements sont reportés immédiatement à l'interface dans retoucher au datasource.

    Le dataSrouce doit cependant être spécifié une première fois pour que le binding soi effectif. après toute modification sur la bidingliste remontera toute seule. (comme pour un dataset)

    Pour ce qui est de la mise à jour manuelle de la datasource il peut y avoir des astuces comme utiliser les méthode SuspendLayout et ResumeLayout() (elle existent sur le formulaire et peut être usi sur le control). Par contre il peut y avoir des scintillement en cas d'opérations asynchrones ou de demandes externes de Refresh() comme le passage d'un formulaire windows au dessus du control.


    Jérémy Jeanson MCP http://blogs.codes-sources.com/JeremyJeanson/ (French or English Spoken)
    mercredi 21 avril 2010 08:03
  • Bonjour,

    J'ai donc associé au Data Source de mes ListBox des StringCollection ou des BindingListe.

    Je vous confirme donc le bon fonctionnement de mes listes en remplaçant mes StringCollection par des BindingList.

    Voici quelques remarques supplémentaires qui viendront, je l'espère, aider ceux qui comme moi recherchent pour la première fois la modification dynamique du contenu d'une liste:

    Rem1: Concernant la "propreté" et maintenabilité du code, l'avantage est tout naturellement à la BindingList, puisqu'elle évite les BeginUpdate, rechargement du datasource et EndUpdate à chaque modif.

    Rem2: Concernant l'effet scintillement évité, je suis persuadé qu'il s'agit bien d'un point important... mais dans ma petite application où la modification d'un datasource n'impacte visuellement que la listbox, je n'ai pas vraiement vu la différence (léger scintillement, il me semble, dans tous les cas).

    Rem3: Il ne faut pas utiliser une BindingList si l'une de vos liste est entièrement rechargée par votre traitement, car dans ce cas le rechargement est très ralenti. Réserver donc les BindingList aux listes que vous chargez une fois , puis qui subit des ajout et suppression d'occurences bien précises.

    Rem4: L'un de mes traitements qui modifie mes DataSource s'effectue dans un thread d'arrière-plan (System.ComponentModel.BackgroundWorker). Dans ce cas, il est à noter que la mise à jour dynamique des listes semble ne pas fonctionner correctement en mode Debug, mais tout est ok une fois la solution générée.

    Je vous remercie encore pour votre aide,

    Cordialement,

    A bientôt

     


    Projet volumineux en cours de migration de Vb6 à VbNet2008 Visual Studio 2008 - VbNET/Vb6(COM)
    lundi 26 avril 2010 07:02