IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Probleme d'instanciation d'une liste pour plusieurs combobox


Sujet :

VB.NET

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut Probleme d'instanciation d'une liste pour plusieurs combobox
    Bonjour

    Je suis confronté actuellement à ce que je pense etre un probleme d'instanciation lorsque j'affecte une même liste (de type BindingSource) aux propriétés Datasource de 4 comboboxs.

    La liste en question est la 1ère colonne (clé primaire) d'une DataTable importée d'Access, triée grâce à un BindingSource. Elle liste les différents "Jobs" existants sous la forme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    "Jobs" <--- en-tête de colonne
    BLM
    BLU
    BRD
    BST
    COR
    DNC
    etc...
    Ce qui donne dans Form1.Designer.vb (section MainWindow InitializeComponents), après avoir "lié" mes 4 comboxs via le designer (glisser-déposer depuis fenetre Source de données MaListe -> Comboboxs):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Combobox1.DataSource = Me.MaListeBindingSource
    Combobox1.DisplayMember = "Jobs"
    Combobox2.DataSource = Me.MaListeBindingSource
    Combobox2.DisplayMember = "Jobs"
    Combobox3.DataSource = Me.MaListeBindingSource
    Combobox3.DisplayMember = "Jobs"
    Combobox4.DataSource = Me.MaListeBindingSource
    Combobox4.DisplayMember = "Jobs"
    Résultat: quand je sélectionne une donnée dans une de ces 4 comboboxs, les 3 autres se mettent automatiquement à la même valeur... Je ne veux pas de ce comportement, d'autant plus que je compte rendre ces combobox mutuellement exclusives afin d'éviter que l'utilisateur ne sélectionne 2 fois le même job.

    Solution: J'ai donc essayé, pour la 1ère combobox par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Combobox1.DataSource = New BindingSource Me.MaListeBindingSource
    Combobox1.DisplayMember = "Jobs"
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Combobox1.DataSource = New Object Me.MaListeBindingSource
    Combobox1.DisplayMember = "Jobs"
    ou autres syntaxes dont je ne m'en souviens plus mais aucune ne fonctionne...

    Quelqu'un aurait-il une idée comment écrire cela correctement, merci d'avance.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    Bonjour,
    il y a la solution, entre autres, de créer autant de BindingSource que de ComboBox.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut Solution 1
    Merci chrismonoye pour cette idée, je pensait a quelquechose de plus "pro" mais bon cela marche.

    Voilà ce que j'avais à l'origine dans Form1.Designer.vb :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            Me.JobsListBindingSource = New System.Windows.Forms.BindingSource(Me.components)
            CType(Me.JobsListBindingSource, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.JobsListBindingSource, System.ComponentModel.ISupportInitialize).EndInit()
            Me.JobsListBindingSource.DataSource = Me.DataSet
            Me.JobsListBindingSource.DataMember = "Jobs List"
            Me.JobsListBindingSource.Sort = "Jobs ASC"
            Me.Combobox1.DataSource = Me.JobsListBindingSource
            Me.Combobox1.DisplayMember = "Jobs"
            Me.Combobox2.DataSource = Me.JobsListBindingSource
            Me.Combobox2.DisplayMember = "Jobs"
            Me.Combobox3.DataSource = Me.JobsListBindingSource
            Me.Combobox3.DisplayMember = "Jobs"
            Me.Combobox4.DataSource = Me.JobsListBindingSource
            Me.Combobox4.DisplayMember = "Jobs"
    ...et c'est devenu :
    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
    26
    27
    28
            Me.JobsListBindingSource1 = New System.Windows.Forms.BindingSource(Me.components)
            CType(Me.JobsListBindingSource1, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.JobsListBindingSource1, System.ComponentModel.ISupportInitialize).EndInit()
            Me.JobsListBindingSource2 = New System.Windows.Forms.BindingSource(Me.components)
            CType(Me.JobsListBindingSource2, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.JobsListBindingSource2, System.ComponentModel.ISupportInitialize).EndInit()
            Me.JobsListBindingSource3 = New System.Windows.Forms.BindingSource(Me.components)
            CType(Me.JobsListBindingSource3, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.JobsListBindingSource3, System.ComponentModel.ISupportInitialize).EndInit()
            Me.JobsListBindingSource4 = New System.Windows.Forms.BindingSource(Me.components)
            CType(Me.JobsListBindingSource4, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me.JobsListBindingSource4, System.ComponentModel.ISupportInitialize).EndInit()        Me.JobsListBindingSource.DataSource = Me.DataSet
            Me.JobsListBindingSource1.DataMember = "Jobs List"
            Me.JobsListBindingSource1.Sort = "Jobs ASC"
            Me.JobsListBindingSource2.DataMember = "Jobs List"
            Me.JobsListBindingSource2.Sort = "Jobs ASC"
            Me.JobsListBindingSource3.DataMember = "Jobs List"
            Me.JobsListBindingSource3.Sort = "Jobs ASC"
            Me.JobsListBindingSource4.DataMember = "Jobs List"
            Me.JobsListBindingSource4.Sort = "Jobs ASC"
            Me.Combobox1.DataSource = Me.JobsListBindingSource1
            Me.Combobox1.DisplayMember = "Jobs"
            Me.Combobox2.DataSource = Me.JobsListBindingSource2
            Me.Combobox2.DisplayMember = "Jobs"
            Me.Combobox3.DataSource = Me.JobsListBindingSource3
            Me.Combobox3.DisplayMember = "Jobs"
            Me.Combobox4.DataSource = Me.JobsListBindingSource4
            Me.Combobox4.DisplayMember = "Jobs"

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Indeed, c'est joli, exactement ce dont j'avais besoin, "magique" dixit dans l'autre thread

    Cependant, je me demande comment je pourrai rendre mes comboboxs mutuellement exclusives, puisque ces nouvelles instances du bindingsource initial ne sont pas nommées ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            Me.MainJob1.DataSource = New BindingSource(Me.JobsListBindingSource, "")
            Me.MainJob1.DisplayMember = "Jobs"
    ...avec Me.MainJob1.Items.??? peutêtre ?

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    Bonjour
    Si j'ai bien compris, un item choisi dans un Combo, doit disparaitre des autres.
    On ne doit pas pouvoir modifier la liste depuis les combo, car ils sont liés à une source de données.
    Donc travailler sur les BindingSources, mais même déclarées, elles sont liées au même Dataset, et modifier l'une modifiera les autres, je pense.
    Une solution consisterait à les isoler les unes des autres, (après avoir renseigné la première) genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
            Me.JobsListBindingSource2 = New BindingSource
            Me.JobsListBindingSource3 = New BindingSource
            Me.JobsListBindingSource4 = New BindingSource
     
            For Each membre As DataRowView In JobsListBindingSource1
                JobsListBindingSource2.Add(membre.Item(0))
                JobsListBindingSource3.Add(membre.Item(0))
                JobsListBindingSource4.Add(membre.Item(0))
            Next
     
            ComboBox2.DataSource = JobsListBindingSource2
            ComboBox3.DataSource = JobsListBindingSource3
            ComboBox4.DataSource = JobsListBindingSource4
    Et le genre d'action suivante, ne devrait pas affecter les combo non concernés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            JobsListBindingSource4.RemoveAt(2)
            JobsListBindingSource3.RemoveAt(1)
            JobsListBindingSource1.RemoveAt(0)

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Merci Chrismonoye, tu as bien compris le problème.

    Cependant, cette solution semble contredire ce que je pensait avoir compris du principe d'instanciation, comme Tomlev a proposé ci dessus: le New BindingSource(JobsListBindingSource, "") est en fait une instance clairement differenciée pour chacune des combobox, si je ne me trompe pas ?
    De plus, cette instanciation ne se fait qu'une seule fois, dans le Form1.Designer.vb section MainWindow InitializeComponents, je ne me trompe pas, toute modification faite par la suite sur chacune de ces instances ne devraient pas modifier la liste initiale (et donc les autres instances par effet domino)?

    D'autre part, je croit qu'en fait ce serait peut-être + simple de travailler directement avec le DataSet pour les propriétés Items(collection) des comboboxs, au lieu de Datasource ? et par la suite pouvoir les manipuler avec Items.AddRange ou Remove pour l'exclusivité mutuelle ?

    Les seules raisons pour lesquelles j'utilisait un BindingSource sont :
    1. le Designer me l'avait imposé par défaut, après avoir glisser-déposer la source de données sur les comboboxs
    2. le BindingSource a 2 propiétés permettant de filtrer et trier ses données ce qui me simplifiait "en principe" mes listes déroulantes déjà triées.
    Or je viens de découvrir ce matin que mes comboboxs ont elles aussi un propiété Sort.
    Du coup, je me demande pourquoi je m'embete avec un BindingSource dans le Datasource, au lieu de travailler avec la collection Items des comboboxs ?

    Enfin, j'avais oublié de préciser :
    1. les comboboxs 1 et 3, appelées MainJob1 et MainJob2, peuvent prendre n'importe quelles valeurs de leur liste, ET ne doivent etre en aucun cas vides (donc initialisées à la 1ère valeur par exemple).
    2. les comboboxs 2 et 4, appelées Subjob1 et SubJob2, peuvent prendre n'importe quelles valeurs de leur liste A L'EXCLUSION de celle selectionnée dans respectivement MainJob1 et MainJob2. Elles sont initialisées vides, donc faut que je trouve un moyen de rajouter la valeur "" a leur liste.

    N'hésitez pas a demander des précisions, je ne suis pas sûr d'avoir été clair

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Pour la solution de Tomlev, je rencontre 2 problèmes.

    le 1er concerne la valeur Null, VB2008 me dit qu'elle n'est plus utilisée mais d'utiliser à la place System.DBNull, mais ca marche pas non plus. J'ai donc simplement mis "", ca a marché au débogage, mais lorsque je me suis remis ce matin à mon projet, j'ai découvert que VB2008 m'avait tout simplement carrement supprimé toutes les lignes datasource = de mes comboboxs... J'ai beau les remettre, si je ferme VB2008 puis reload, il me les supprime...

    le 2nd probleme concerne la manipulation des instances de JobsListBindingSource. Comme expliqué ci dessus, un BindingSource possede les propiétés Sort et Filter.
    Le Sort à la limite j'aurais pu m'en passer et travailler directement avec le Dataset puis mettre la propriété Sorted de mes comboboxs a True.
    En revanche, le filter m'interesse pour faire l'exclusivité mutuelle entre comboboxs. Comment m'en servir ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            Me.SubJob1.DataSource = New BindingSource(Me.JobsListBindingSource.Filter(Me.JobsListBindingSource.Member("Jobs") != Me.MainJob1.SelectedItem), ???)
            Me.SubJob1.DisplayMember = "Jobs"

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Masamunai Voir le message
    j'ai découvert que VB2008 m'avait tout simplement carrement supprimé toutes les lignes datasource = de mes comboboxs... J'ai beau les remettre, si je ferme VB2008 puis reload, il me les supprime...
    Euh, si tu fais ça dans le code généré par le designer, c'est normal, VS l'écrase à chaque fois que tu modifies quelque chose dans le designer...

    Citation Envoyé par Masamunai Voir le message
    le 2nd probleme concerne la manipulation des instances de JobsListBindingSource. Comme expliqué ci dessus, un BindingSource possede les propiétés Sort et Filter.
    Le Sort à la limite j'aurais pu m'en passer et travailler directement avec le Dataset puis mettre la propriété Sorted de mes comboboxs a True.
    En revanche, le filter m'interesse pour faire l'exclusivité mutuelle entre comboboxs. Comment m'en servir ?
    Déjà il faut garder des références vers tes BindingSources dans des champs de ta classe. Ensuite, il faut affecter une chaine de caractère à la propriété Filter, par exemple bindingSource1.Filter = "Jobs <> 'BLM'"

  10. #10
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Est-que les DataView ne seraient pas la réponse à votre problème :

    En outre, DataView peut être personnalisé pour présenter un sous-jeu de données à partir de DataTable. Cette fonctionnalité vous permet d'avoir deux contrôles liés au même DataTable, mais affichant des versions différentes des données.
    Source : http://msdn.microsoft.com/fr-fr/libr...8VS.80%29.aspx

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Bonsoir

    Effectivement c'est une une solution adaptée Moldavi, merci.

    Voilà ce que j'ai implémenté en m'inspirant de l'exemple dans le lien de Moldavi:
    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
    Public Class MainWindow
     
        Private Sub MainWindow_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
     
            ...
     
            Dim MainJob1View As DataView = New DataView(DataSet.Jobs_List)
            Dim SubJob1View As DataView = New DataView(DataSet.Jobs_List)
            SubJob1View.AddNew()("Jobs") = ""
            Me.MainJob1.DataSource = MainJob1View
            Me.SubJob1.DataSource = SubJob1View
            Me.MainJob1.SelectedItem = MainJob1View.Item(0)
     
        End Sub
     
        ...
     
    End Class
    Le code ci dessus corresponds a l'initialisation des 2 comboboxs.
    Cela m'affiche dans la liste déroulante du combobox MainJob1 20 lignes "System.Data.DataRowView", et 21 lignes "System.Data.DataRowView" pour SubJob1.
    On dirait j'ai dû faire une erreur de syntaxe, mais je ne vois pas où ni comment ...
    Au débogage, les comboboxs n'affichent rien du tout dans la partie éditable, ce qui est ok pour SubJob1, mais pas pour MainJob1 qui doit absolument pas être vide.

    Sinon après, je compte rajouter un sub Mainjob1.SelectedItemChanged et sub Subjob1.SelectedItemChanged dans lesquels j'utiliserai la méthode Filter sur les 2 DataViews. Suis-je sur la bonne voie où c'est dans le mur ?

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    Bonjour,
    Moldavi = +1
    dans le load, manque displaymember :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            Me.MainJob1.DataSource = MainJob1View
            Me.MainJob1.DisplayMember = "Jobs"
    Puis on créé le dataview du combo secondaire, avec un filtre excluant l'item sélectionné du combo primaire, genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        Private Sub MainJob1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MainJob1.TextChanged
     
            Dim SubJob1View As DataView = New DataView(Me.DsNoms.Tables("Jobs_List"))
     
            Dim item As String = MainJob1.Text
            SubJob1View.RowFilter = "Jobs <> '" & MainJob1.Text & "'"
     
            SubJob1View.Sort = "Jobs"
            SubJob1View.RowStateFilter = DataViewRowState.CurrentRows
     
            Me.SubJob1.DataSource = SubJob1View
            Me.SubJob1.DisplayMember = "Jobs"

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Ca marche niquel !

    Merci a vous 3.

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    A noter que la proposition de Tomlev, à savoir filtrer le BindingSource fonctionne de la même manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.JobsListBindingSource4.Filter = "Jobs <> '" & MainJob2.Text & "'"

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Dev infopath pour modifier 1 item d'une liste et plusieurs items d'une autre liste
    Par Nico2010 dans le forum Développement Sharepoint
    Réponses: 2
    Dernier message: 19/04/2012, 16h30
  2. une zone de liste pour plusieurs champs
    Par mumu64 dans le forum IHM
    Réponses: 5
    Dernier message: 26/11/2008, 12h02
  3. Quel objet utiliser pour afficher une liste de plusieurs résultats
    Par jlachapelle dans le forum Windows Forms
    Réponses: 1
    Dernier message: 15/08/2008, 20h33
  4. Réponses: 1
    Dernier message: 13/06/2008, 17h24
  5. [template] Instanciation d'une liste de types pour un plugin
    Par Matthieu Brucher dans le forum C++
    Réponses: 6
    Dernier message: 11/01/2007, 07h54

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