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 :

ContextMenu dynamique - MenuItem => Les sous menus ne s'ouvrent pas. [MVVM]


Sujet :

Windows Presentation Foundation

  1. #1
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut ContextMenu dynamique - MenuItem => Les sous menus ne s'ouvrent pas.
    Bonjour @ tous,

    Je charge un contextMenu depuis le MVVM avec cette méthode:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
                            <DataGrid.ContextMenu>
                                <ContextMenu x:Name="cmuMain">
                                    <ContextMenu.ItemsSource>
                                        <Binding Path="ClicDroit"/>
                                    </ContextMenu.ItemsSource>
                                </ContextMenu>
                            </DataGrid.ContextMenu>
    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
                    var icMainDefaultGroup = new string[] { "Synthétique", "Demandes", "Comm", "Mouvement", "Fact" };
                    var icMainDefault = new string[,] { {FCT_AFF_AXEAFF_AFF, "Fiche Affaire"}, {FCT_AFF_AXEAFF_AFFTAC, "Tâche de l'affaire"}, {$"{FCT_AFF_AXEAFF_AFF}", "Budgets|Budget"},
                        { FCT_AFF_SAI_RAENAT, "RAE"}, {FCT_AFF_RES_PLAPRE, "Plan de présentation"}, {FCT_AFF_RES_CONPRE, "Globale#0"}, {$"{FCT_AFF_RES_CONPREDET}", "Détaillée#0"},
                        {"Sep", "-"}, {FCT_ACH_DAPLIS, "Liste|Liste#1"}, {$"{FCT_ACH_DAPLISDET}", "Liste détaillée#1"}, {FCT_ACH_COMFOULIS, "Liste|Liste#2"}, {$"{FCT_ACH_COMFOULISDET}", "Liste détaillée#2"},
                        {FCT_ACH_MOUSTOLIS, "Liste|Liste#3"}, {$"{FCT_ACH_MOUSTOLISDET}", "Liste détaillée#3"},{FCT_ACH_FACFOULIS, "Liste|Liste#4"},{$"{FCT_ACH_FACFOULISDET}", "Liste détaillée#4"},
                        {"Sep", "-"}, {FCT_FAC_DEVVENLIS, "Devis clients|Liste"}, {FCT_FAC_CDEVENLIS, "Commandes clients|Liste"},{ FCT_FAC_LIVCLILIS, "Livraisons clients|Liste"},
                        {FCT_FAC_FACCLILIS, "Factures clients|Liste"}, {FCT_FAC_PREFAC, "Prévisionnel de facturation" } };
                    for (int i = 0; i < icMainDefault.GetLength(0); i++) {
                        var tabTmp = icMainDefault[i, 1].ToString().Split(new char[] { '#' });
                        var Code = tabTmp[0].Split(new char[] { '|' });
                        if (Code[0] == "-") { ClicDroit.Add(new Separator()); continue; }
                        var ic = new MenuItem() { Header = Code[0], Name = icMainDefault[i, 0] };
                        if (Code.Length > 1) ic.Tag = Code[1];
                        ic.Click += icCmuMain_Click;
                        int tmp = 0;
                        if ((tabTmp.Length > 1) && (int.TryParse(tabTmp[1], out tmp)) && (tmp < icMainDefaultGroup.Length)) {
                            var miPar = ClicDroit.OfType<MenuItem>().Where(x => x.Name == $"cmuMainPar{tmp}").SingleOrDefault();
                            if (miPar == null) {
                                miPar = new MenuItem() { Header = icMainDefaultGroup[tmp], Name = $"cmuMainPar{tmp}" }; // 
                                ClicDroit.Add(miPar);
                            }
                            miPar.Items.Add(ic);
                        } else {
                            ClicDroit.Add(ic);
                        }
                    } // Fin foreach
    Le éléments à la racine s'affichent bien, mais les sous menus ne se popup pas
    Je suis sur qu'ils sont bien chargés car si je met "miPar.IsSubmenuOpen = true;", on les voit bien ouvert lors du premier lancement.
    De plus, si j'instancie l’événement "miPar.ContextMenuOpening += icCmuMainParent_ContextMenuOpening;", je peux les ouvris via le clic droit... Mais ça ne me satisfait pas.

    De plus, pourquoi les événements "Click, MouseDown, MouseRightButtonDown, .." ne se déclenchent pas si je les instancie ?

    Merci d'avance.
    David.

  2. #2
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 51
    Points : 72
    Points
    72
    Par défaut
    Il faut dire à tes menuitems de premier niveau où aller chercher les subitems. Va voir ça :

    http://stackoverflow.com/questions/1...r-context-menu

  3. #3
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut
    Je ne suis pas sur de comprendre...

    J'ai bien essayé de passer par un itemSource
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    miPar.ItemsSource = new List<MenuItem>() { ic };
    A la place de "miPar.Items.Add(ic);" Mais ça ne change rien.

    Faut-il que je refasse une nouvelle propriété (ou une liste de ItemsCollection") et affectation/binding pour chaque MenuItem qui a des enfants ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClicDroitPar = new ItemsControl().Items;
    En dynamique, ça va pas être pratique.
    David.

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 51
    Points : 72
    Points
    72
    Par défaut
    Le premier niveau de menuitems est bindé sur la liste ClicDroit dans ton exemple de code. Chaque menuitem qui va être créé doit savoir dans quelle propriété de chaque élément de la liste ClicDroit il doit aller chercher ses subitems. C'est la solution qui est donnée dans l'exemple du lien que j'ai posté.

    Question : qu'y a-t-il dans ClicDroit ?

  5. #5
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut
    Mon clicDroit est Déclaré comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public ItemCollection ClicDroit { get { return _ClicDroit; } set { _ClicDroit = value; RaisePropertyChanged(nameof(ClicDroit)); } }
    Et instancié comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClicDroit = new ItemsControl().Items;
    Donc, tu dis que chaque menuItem possédant des enfants doit être bindé sur une propriété de type ItemCollection.

    Mais étant dynamique je ne sais pas à l'avance combien de menu ayant des sous menus je vais avoir.
    Je dois donc en créer un nombre que je pense maximum et ne pas instancier ceux qui ne seront pas utilisés ?
    C'est pas très propre...

    ... Je regarde le lien que tu m'as passé, mais j'ai du mal à le transposer à mon cas de figure... Il n'y a aucun code, juste un style.
    Je vois que son ContextMenuItemsSource correspond à mon ClicDroit, mais pour les autres propriétés, ça ne colle pas avec ma structure.
    David.

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 51
    Points : 72
    Points
    72
    Par défaut
    Utilises des observablecollections :

    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 MonMenuItem
            {
                public string Header { get; set; }
     
                public System.Collections.ObjectModel.ObservableCollection<MonMenuItem> Children { get; set; }
            }
     
            public System.Collections.ObjectModel.ObservableCollection<MonMenuItem> ClicDroit { get { return _ClicDroit; } set { _ClicDroit = value; RaisePropertyChanged(nameof(ClicDroit)); } }
     
     
    <ContextMenu ItemsSource = "{Binding ClicDroit}" >
        < ContextMenu.ItemContainerStyle >
            < Style TargetType="MenuItem">
                <Setter Property = "Header" Value="{Binding Header}"></Setter>
                <Setter Property = "ItemsSource" Value="{Binding Children}"></Setter>
            </Style>
         </ContextMenu.ItemContainerStyle>
    </ContextMenu>

  7. #7
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut
    En fait, si je comprends bien, son ContextMenuItemsSource est une Liste d'object spécifique qui a 3 propriétés:
    - string ContextMenuCommandHeader;
    - RelayCommand ContextMenuCommand; // ??? c'est possible de binder comme ça ?
    - List<[type de ContextMenuItemsSource]> ContextMenuSubItems;

    Donc, dans ce cas, il faudrait juste que je fasse un style de ce type là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <Style TargetType="MenuItem">
        <Setter Property="ItemsSource" Value="{Binding ClicDroitEnfants}"/>
    </Style>
    Et que je mette tous les enfants dans "ClicDroitEnfants", du type "ItemCollection", non ?
    David.

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 51
    Points : 72
    Points
    72
    Par défaut
    Oui, mais utilises des observablecollections à la place des itemscollections.

  9. #9
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut
    On a écrit en même temps, mais heureusement, on a été dans le même sens.
    Oui, ObservableCollection ou List, même logique.

    Je comprends, mais ça m’embête car j'utilise pas mal du comportement des ItemsControl (je n'ai pas tout mis mon code... Tag, Icon, événements, ...) ça m'obligerait à créer un objet presque similaire au control... Et donc d'autre bricoles qui amèneront à d'autres problèmes.

    J'ai réussi à m'en sortir comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    miPar.MouseMove += icCmuMainParent_MouseMove; // BUG: Sinon, le sous menu ne s'affiche pas...
     
            private void icCmuMainParent_MouseMove(object sender, MouseEventArgs e) {
                var s = (MenuItem)sender;
                s.IsSubmenuOpen = true;
            }
    Allez savoir pourquoi 90% des évenements ne fonctionnent pas mais celui là si.
    C'est pas super propre et le comportement visuel n'est pas génial, mais en attendant mieux... (que Microsoft finalise vraiment son framework WPF... )

    Merci pour tes lumières dzediar.
    David.

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 51
    Points : 72
    Points
    72
    Par défaut
    Dans ce cas utilises directement une observablecollection de menuitems. Si tu mets des menuitems dans itemssource d'un contextmenu ils devraient directement être affichés.

    Tu as tout dans la classe menuitem normalement (icône, ...).

    En plus tu as les propriétés items et et itemssource normalement.

  11. #11
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut
    Bonne idée, mais je rencontre déjà le premier problème: Les séparateurs.

    [Edit]Pour info, ça fonctionne si je commente les séparateurs... Cas de conscience !
    David.

  12. #12
    Membre averti Avatar de dacid
    Homme Profil pro
    Inscrit en
    Juin 2003
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 063
    Points : 420
    Points
    420
    Par défaut
    Hé hé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (Code[0] == "-") { ClicDroit.Add(new MenuItem() { Height=4, IsEnabled=false, Background=new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(150, 150, 150)) }); continue; } // ClicDroit.Add(new Separator());
    WPF a été inspiré par Mac Giver...

    Merci encore dzediar
    David.

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

Discussions similaires

  1. [IE 7] Les sous-menus ne s'affichent pas
    Par slowpoke dans le forum IE
    Réponses: 0
    Dernier message: 07/07/2009, 11h02
  2. Menu CSS : les sous menus ne s'affichent pas
    Par pci130 dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 29/05/2009, 19h33
  3. [ContextMenu] Comment mon style peut gérer les sous-menus ?
    Par Gregory.M dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 18/09/2008, 23h52
  4. Comment différencier les sous-menus d'un TMenuItem ?
    Par laclac dans le forum Débuter
    Réponses: 4
    Dernier message: 08/01/2008, 17h31
  5. [DOM] Menu déroulant et DOM. Afficher les sous-menus cachés
    Par glenouve dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 14/11/2007, 11h42

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