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

Windows Presentation Foundation Discussion :

Combobox dans TabItem : impossible d'initialiser Combobox.SelectedIndex


Sujet :

Windows Presentation Foundation

  1. #1
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut Combobox dans TabItem : impossible d'initialiser Combobox.SelectedIndex
    Bonjour tout le monde,

    Dans une application WPF, j'ai une liste déroulante dans un onglet (on va parler en français d'abord, le code suivra ). Lorsque l'utilisateur sélectionne cet onglet, la liste déroulante s'initialise et se place sur le premier élément.
    Hors, cette dernière action relance l'évènement tabControl1_SelectionChanged et l'action se répète indéfiniment jusqu'au dépassement de pile.

    Pour plus de clarté, voici les bouts de code :
    XAML :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <TabControl Name="tabControl1" SelectionChanged="tabControl1_SelectionChanged">
      <TabItem Header="Tab1">
        [...]
      </TabItem>
      <TabItem Header="Tab2">
        <ComboBox Name="cb1" />
      </TabItem>
    </TabControl>
    Code Behind (C#) :
    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
    private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      if (tabControl1.SelectedIndex == 1) // si ont est sur Tab2
      {
        Dictionary<string, string> DicoCbItems = new Dictionary<string, string>();
        DicoCbItems.Add("lorem ipsum", "1");
        DicoCbItems.Add("oui oui", "2");
        DicoCbItems.Add("superman", "3");
    
        Binding BindCb = new Binding();
        BindCb.Source = DicoCbItems;
        cb1.DisplayMemberPath = "Key";
        cb1.SelectedValuePath = "Value";
        cb1.SetBinding(ComboBox.ItemsSourceProperty, BindCb);
    
        // prochaine instruction déclenche l'évènement tabControl1_SelectionChanged et 
        // ça tourne en boucle jusqu'au dépassement de pile
        cb1.SelectedIndex = 0; 
      }
    }
    Est-ce que quelqu'un sait comment faire autrement (proprement*) ?
    Si vous savez pourquoi ça fait cela, je suis aussi preneur, voire même beaucoup plus intéressé que pour le comment!

    * : par "proprement", je veux dire plus proprement qu'un flag "bool Tab2IsInitializing" pour ne faire l'évènement qu'une fois à la fois, solution que j'ai rapidement mis en place.

  2. #2
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Normalement, l'évènement SelectionChanged d'un TabControl n'est lancé que lorsque l'onglet sélectionné change.
    Or d'après ce que tu nous dit, c'est le fait de changer l'item sélectionné de la ComboBox qui rappelle la méthode tabControl1_SelectionChanged().

    Est-ce que par hasard, tu n'aurais pas ajouté la méthode tabControl1_SelectionChanged() sur l'évènement SelectionChanged de ta ComboBox ?

  3. #3
    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 : 43
    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
    Par défaut
    Citation Envoyé par seiryujay Voir le message
    Est-ce que par hasard, tu n'aurais pas ajouté la méthode tabControl1_SelectionChanged() sur l'évènement SelectionChanged de ta ComboBox ?
    Exactement ce que j'allais suggérer...

  4. #4
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    Citation Envoyé par seiryujay Voir le message
    Est-ce que par hasard, tu n'aurais pas ajouté la méthode tabControl1_SelectionChanged() sur l'évènement SelectionChanged de ta ComboBox ?
    Non, aucun évènement d'implémenter sur la combobox.

    Je n'ai jamais rencontré ce type de problème avant de me mettre dans la WCF mais depuis quelques semaines que je m'y mets, j'ai bcp de surprises...

    Si ça peut aider, car je suppose que ce n'est pas forcément normal : lors du démarrage, le tabcontrol (de l'espace de noms System.Windows.Controls) a son SelectionChanged qui est levé plusieurs fois au démarrage alors que je ne touche jamais à son SelectedIndex

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    y'a un comportement spécial des tabcontrol pour les tabitem
    en fait il n'initialise les objets qui sont dedans seulement quand le tabitem est sélectionné
    moi je te suggèrerais de faire un binding sur une collection, ce qui preserverait a la fois ce qu'il y a dedans et la sélection

  6. #6
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Une question toute bête aussi : as-tu besoin de recharger le contenu de ta ComboBox à chaque fois que ton TabItem est activé ?
    Si ce n'est pas utile, t'as plus de problème

  7. #7
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    J'ai réessayé avec un nouveau projet application WPF (Visual Studio 2008) et j'ai toujours le pb.

    Voilà les étapes pour reproduire :
    - créer un nouveau projet applicationWPF
    - mettre un tabcontrol sur Window1
    - ajouter un onglet
    - mettre un combobox sur un des onglets (le second dans mon exemple)
    - implémenter l'évènement tabControl1_SelectionChanged avec le code suivant :
    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
    private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
          Dictionary<string, string> DicoCbItems = new Dictionary<string, string>();
          DicoCbItems.Add("lorem ipsum", "1");
          DicoCbItems.Add("oui oui", "2");
          DicoCbItems.Add("superman", "3");
     
          Binding BindCb = new Binding();
          BindCb.Source = DicoCbItems;
          comboBox1.DisplayMemberPath = "Key";
          comboBox1.SelectedValuePath = "Value";
          comboBox1.SetBinding(ComboBox.ItemsSourceProperty, BindCb);
     
          // prochaine instruction déclenche l'évènement tabControl1_SelectionChanged et 
          // ça tourne en boucle jusqu'au dépassement de pile
          comboBox1.SelectedIndex = 0;
        }
    Exécutez le projet et essayez de choisir autre chose que le premier élément ... impossible.

    Comme si le Combobox hérite de l'évènement selectionChanged de son parent (c'est de la science fiction?)


    ---
    Au cas où, le mini-projet en pièce jointe

    Merci pour le temps consacré,
    Arnaud
    Fichiers attachés Fichiers attachés

  8. #8
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    Citation Envoyé par seiryujay Voir le message
    Une question toute bête aussi : as-tu besoin de recharger le contenu de ta ComboBox à chaque fois que ton TabItem est activé ?
    Si ce n'est pas utile, t'as plus de problème
    Je préfèrerai parce que ça provient d'un fichier externe de configuration (qui n'est pas gros et qui ne change pas souvent donc je ne le recharge pas à chaque fois non plus), ça évite d'avoir à redémarrer l'application pour prendre en compte les modifications.

  9. #9
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Ok, comportement intéressant...
    Je te conseille de regarder cette discussion.

    Et notamment ce passage :
    This is because both ComboBox and TabControl are derived from Selector, and the SelectionChanged event is a routed event, so the child ComboBox' SelectionChanged event will be routed to its parent control TabControl. Just like mouse event can be routed from a child element to its parent element.
    C'est le genre de truc qui paraît louche au premier abord mais qui a une explication rationnelle.

    Donc en gros, tu peux :
    - soit rajouter le test suivant au début de ton évènement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (sender == e.OriginalSource)
    - soit rajouter une méthode sur l'évènement SelectionChanged de ta ComboBox qui fera (entre-autre) afin de stopper la propagation de ton RoutedEvent

    Voilà.

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    tu as une solution simple c'est de mettre tout ton code dans le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private void tabItem2_GotFocus(object sender, RoutedEventArgs e)
        {
     
        }
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <TabItem Header="tabItem2" Name="tabItem2" GotFocus="tabItem2_GotFocus">
    bien sur

    maintenant il faut proteger le code pour le repassage dans le tab

    bon sinon une autre alternative qui me parrait plus propre
    dans ton tabitem tu met
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <TabItem Name="tabItem2" GotFocus="tabItem2_GotFocus" Loaded="tabItem2_Loaded">
                    <TabItem.Header >
                        <TextBlock Text="sdqsqsqsd"  MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" />
                    </TabItem.Header>
                    <Grid>
    puis tu met le code dans le TextBlock_MouseLeftButtonDown
    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
     
     if (tabControl1.SelectedIndex == 1) return;
            Dictionary<string, string> DicoCbItems = new Dictionary<string, string>();
            DicoCbItems.Add("lorem ipsum", "1");
            DicoCbItems.Add("oui oui", "2");
            DicoCbItems.Add("superman", "3");
     
            Binding BindCb = new Binding();
            BindCb.Source = DicoCbItems;
            comboBox1.DisplayMemberPath = "Key";
            comboBox1.SelectedValuePath = "Value";
            comboBox1.SetBinding(ComboBox.ItemsSourceProperty, BindCb);
     
            comboBox1.SelectedIndex = 0;
            textBox1.Text = "sdfghjklm";

  11. #11
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    Citation Envoyé par seiryujay Voir le message
    Ok, comportement intéressant...
    Pour l'instant, j'avoue que je prends ça plus comme quelquechose qui m'a fait perdre une petite journée.
    Mais je suis à chaud là, c'est pour ça. Une clope et ça ira mieux (message pour les enfants et ados : fumer n'est pas bien, une fois que l'on a commencé, on se dit pendant des années qu'on va arrêter et on ne le fait jamais).

    Je te conseille de regarder cette discussion.

    Et notamment ce passage :

    Donc en gros, tu peux :
    - soit rajouter le test suivant au début de ton évènement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (sender == e.OriginalSource)
    - soit rajouter une méthode sur l'évènement SelectionChanged de ta ComboBox qui fera (entre-autre) afin de stopper la propagation de ton RoutedEvent

    Voilà.
    ho purée les saligots chez Microsoft.
    Merci !!
    Tu googleïses mieux que moi.

    C'est le genre de truc qui paraît louche au premier abord mais qui a une explication rationnelle.
    L'explication que j'ai lu dans la discussion ne me paraît pas rationnelle. Si on avait par défaut le comportement d'avant (l'évènement n'est pas automatiquement routé aux parents) mais qu'on a la possibilité de le faire, je dirai super. Mais là, moyen.
    Cependant, j'aime bien ta façon de voir car sans aucun jugement de valeur.

    Merci encore pour la solution

  12. #12
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    Citation Envoyé par ikeas Voir le message
    tu as une solution simple c'est de mettre tout ton code dans le
    private void tabItem2_GotFocus(object sender, RoutedEventArgs e)
    {

    }
    avec
    <TabItem Header="tabItem2" Name="tabItem2" GotFocus="tabItem2_GotFocus">
    bien sur

    maintenant il faut proteger le code pour le repassage dans le tab
    Merci, mais ça posait le même problème.
    Le ; fonctionne impeccable.

  13. #13
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    en fait j'ai corrige mon message ave une alternative plus "sexy"
    ce qu'on constate c'est qu'il manque un selected sur tabitem, ca doit pouvoir se rajouter
    moi je trouve que c'est plus sympa d'impacter sur un event lié au tab item plutot qu'a un autre (enfin comme la combo par exemple)

  14. #14
    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 : 43
    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
    Par défaut
    Effectivement, j'observe le même comportement... c'est surprenant
    En fait il faut juste tester si le e.OriginalSource == tabControl1, et ça marche

  15. #15
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    Citation Envoyé par ikeas Voir le message
    en fait j'ai corrige mon message ave une alternative plus "sexy"
    Pour éviter le repassage (tien, j'en ai à faire ce soir d'ailleurs) dans l'évènement, j'avais au départ déclaré une variable globale : un booléen IsTab2Initialising

    dans le code du tabcontrol1_selectedIndexChanged, j'avais mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    If (IsTab2Initializing)
    {
      return; 
    }
    IsTab2Initializing = true;
    [... le traitement ...]
    IsTab2Initializing = false;
    moins bidouilleux je pense (mais c'est une histoire de goût)

    maintenant, avec la compréhension des évènements routés en WPF, je dormirai moins bête ce soir.

    merci à tous ceux qui ont répondu à l'appel. Un autre va suivre vu la réussite inattendue ici

  16. #16
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    a mon avis ca serait interessant de creer un message selected sur le tabitem
    ca simplifirais et de loin

  17. #17
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Citation Envoyé par ikeas Voir le message
    en fait j'ai corrige mon message ave une alternative plus "sexy"
    ce qu'on constate c'est qu'il manque un selected sur tabitem, ca doit pouvoir se rajouter
    moi je trouve que c'est plus sympa d'impacter sur un event lié au tab item plutot qu'a un autre (enfin comme la combo par exemple)
    Moi aussi ça me fait bizarre de rajouter un évènement vide qui affecte juste le e.Handled (c'est le genre de truc qui peut sauter par la suite si y'a pas un commentaire explicite du pourquoi de la méthode).

    C'est pour ça que le test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (sender == e.OriginalSource)
    englobant le contenu de la méthode appelée sur l'évènement SelectionChanged du TabControl me paraît plus adapté...


    Tu googleïses mieux que moi.
    Des années de pratique ^^ (faut dire que j'ai galéré sur pas mal de problèmes aussi... )


    L'explication que j'ai lu dans la discussion ne me paraît pas rationnelle.
    Pourquoi ?
    Tu comprends bien le comportement sur un évènement souris ? Celui-ci est propagé de l'élément qui reçoit le clic vers ses éléments parents.
    Ben là c'est pareil mais avec le SelectionChanged d'un élément dérivant de Selector qui est propagé vers ses éléments parents dérivant de Selector (autrement dit TabControl, ListBox, ComboBox).


    Si on avait par défaut le comportement d'avant (l'évènement n'est pas automatiquement routé aux parents) mais qu'on a la possibilité de le faire, je dirai super. Mais là, moyen.
    Ca c'est une autre histoire. Là faut voir directement avec monsieur Microsoft


    Cependant, j'aime bien ta façon de voir car sans aucun jugement de valeur.
    Ca c'est parce que j'ai pas perdu une journée de boulot à batailler dessus :p

  18. #18
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Par défaut
    tiens j'ai trouve encore mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <TabItem Name="tabItem2" Selector.Selected="_Selected">
    et tu met ton code dans le _Selected

  19. #19
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Citation Envoyé par ikeas Voir le message
    tiens j'ai trouve encore mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <TabItem Name="tabItem2" Selector.Selected="_Selected">
    et tu met ton code dans le _Selected
    Bien vu !

  20. #20
    Membre éclairé
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Par défaut
    Citation Envoyé par ikeas Voir le message
    tiens j'ai trouve encore mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <TabItem Name="tabItem2" Selector.Selected="_Selected">
    et tu met ton code dans le _Selected
    Ca ne fait que quelques semaines que je me suis remis au C# (la dernière fois remontant à 2005 avec du .NET 1.1 et un peu de 2.0 !).
    Et je tiens à vous dire que vos solutions me paraissent monstrueuses. Y'a trop de choses qui ont changé en .NET 3.5 !

    Mais ta réponse est juste. Adoptée.

    et un double-résolu, un.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. initialisation d'une combobox dans Visual Studio 2012
    Par elmanu20 dans le forum Visual C++
    Réponses: 6
    Dernier message: 26/11/2013, 14h28
  2. Réponses: 8
    Dernier message: 07/01/2013, 15h46
  3. Initialiser Combobox dans une cellule
    Par Charles1104 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 04/12/2012, 08h09
  4. Réponses: 4
    Dernier message: 15/04/2010, 10h20
  5. [VBA-excel]initialiser une combobox dans worksheet
    Par Mugette dans le forum Macros et VBA Excel
    Réponses: 16
    Dernier message: 20/09/2006, 11h29

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