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 :

Menu avec contenu dynamique et à plusieurs niveaux [MVVM]


Sujet :

Windows Presentation Foundation

  1. #1
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 242
    Par défaut Menu avec contenu dynamique et à plusieurs niveaux
    Bonjour,

    J'ai actuellement un problème pour créer un menu WPF "dynamique", dans le sens où une partie de son contenu est variable.
    C'est un menu pour lancer un certain nombre de jeux.

    Je voudrais aboutir au menu suivant:

    Mes jeux
    > Jeu 1
    > Jeu 2
    > ...
    > Jeu N
    Séparateur
    > Quitter

    Jusque là, j'ai à peu près réussi. Mes binding fonctionnent tous correctement.

    Et pour chaque jeu, il y aurait un sous-menu, qui est lui toujours le même.
    > Nouvelle partie
    > Préférences
    C'est sur cette partie que je bloque : je n'arrive pas à définir le sous-menu de chaque jeu dans mon code, je ne vois pas comment faire.

    Voici mon code XAML:
    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
    29
    30
    31
    32
     
        <Menu>
            <Menu.Resources>
                <CollectionViewSource x:Key="GamesList" Source="{Binding GamesModuleVM}" />
            </Menu.Resources>
     
            <MenuItem>
                <MenuItem.Header>
                    <TextBlock Text="Mes jeux" />
                </MenuItem.Header>
                <MenuItem.ItemContainerStyle>
                    <Style>
                        <Setter Property="MenuItem.Header" Value="{Binding ApplicationGame.Name}" />
                        <Setter Property="MenuItem.Icon" Value="{Binding ApplicationGame.SmallImage}" />
                        <Setter Property="MenuItem.Command" Value="{Binding StartCommand}" />
                        <!--<Setter Property="MenuItem.Items">
                            <Setter.Value>                            
                                <MenuItem Header="Nouvelle partie" Command="{Binding StartCommand}" />
                                <MenuItem Header="Préférences" Command="{Binding EditSettingsCommand}" />
                            </Setter.Value>
                        </Setter>-->
                    </Style>
                </MenuItem.ItemContainerStyle>
                <MenuItem.ItemsSource>
                    <CompositeCollection>
                        <CollectionContainer Collection="{Binding Source={StaticResource GamesList}}" />
                        <Separator />
                        <MenuItem Header="Quitter" />
                    </CompositeCollection>
                </MenuItem.ItemsSource>
            </MenuItem>
        </Menu>
    Pouvez-vous me donner quelques pistes ?

    Merci !

  2. #2
    Membre du Club
    Profil pro
    Technicien maintenance
    Inscrit en
    Mars 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 9
    Par défaut
    Je pense que tu peux utiliser un HierarchicalDataTemplate, ça donnerait quelque-chose comme ça :

    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
     
    <Menu>
    	<MenuItem Header="Mes jeux"  ItemsSource="{Binding GamesModuleVM}">
    		<MenuItem.ItemTemplate>
    			<HierarchicalDataTemplate>
    				<TextBlock Text="{Binding ApplicationGame.Name}" />
                                    <Image Source="{Binding ApplicationGame.SmallImage}" />
                                     <HierarchicalDataTemplate.ItemTemplate>
                                              <TextBlock Text="Nouvelle partie" Command="{Binding StartCommand}" />
                                              <TextBlock Text="Préférences" Command="{Binding EditSettingsCommand}" />
                                     </HierarchicalDataTemplate.ItemTemplate>
    			</HierarchicalDataTemplate>
    		</MenuItem.ItemTemplate>
    	</MenuItem>
    </Menu>

  3. #3
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 242
    Par défaut
    Je note bien l'idée des Hierarchicale DataTemplate. Ca doit surement être un truc comme ça, mais même avec ton code, je n'arrive pas à mes fins (ça ne compile hélas pas, et il n'y a plus non plus la partie en dessous avec le "quitter").

    As-tu des idées pour comment corriger?

  4. #4
    Membre du Club
    Profil pro
    Technicien maintenance
    Inscrit en
    Mars 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 9
    Par défaut
    Ha ouais, désolé, c'était peut-être une fausse-piste.
    Je vais changer mon fusil d'épaule...

    Dans ton code, essaies de remplacer toute ta partie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <MenuItem.ItemContainerStyle>...</MenuItem.ItemContainerStyle>
    par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <MenuItem.ItemTemplate>
        <DataTemplate>
            <MenuItem Header="{Binding ApplicationGame.Name}" Icon="{Binding ApplicationGame.SmallImage}" Command="{Binding StartCommand}">
    		<MenuItem Header="Nouvelle partie" Command="{Binding StartCommand}" />
    		<MenuItem Header="Préférences" Command="{Binding EditSettingsCommand}" />
    	</MenuItem>
        </DataTemplate>
    </MenuItem.ItemTemplate>

  5. #5
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 242
    Par défaut
    Ca compile, mais ça ne fait pas vraiment ce qu'il faut .
    Il m'a mis un MenuItem à l'intérieur du menuItem déjà prégénéré (ce qui est normal je pense). Et quand je clique sur la flèche du sous-menu, rien ne s'affiche.

    D'autres idées ?

  6. #6
    Membre du Club
    Profil pro
    Technicien maintenance
    Inscrit en
    Mars 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 9
    Par défaut
    J'avoue que je sèche un peu.
    Ma première idée, de passer par un hierarchicalDatatemplate, se basait sur ce qu'on peut faire avec un contrôle treeview, je pensais pouvoir transposer ça à un contrôle menu, mais apparemment ce n'est pas si simple.

    Regarde sur ce lien, tu pourras peut-être dégager une piste :
    http://blogs.msdn.com/b/mikehillberg...p-by-step.aspx

  7. #7
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 242
    Par défaut
    Continuons donc sur ce HierarchicalDataTemplate...

    Mon code a un peu évolué, mais ne marche toujours pas.
    J'arrive à avoir la bonne structure, mais aucun Binding ne fonctionne !

    J'ai aussi du ajouter un view model pour le sous menu des actions, je voyais pas comment faire autrement : obliger de binder le ItemsSource du HierarchicalDataTemplate avec quelque chose.

    Mon Xaml :
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    <Menu>
            <Menu.Resources>
                <CollectionViewSource x:Key="GamesList" Source="{Binding GamesModuleVM}" />
     
                <HierarchicalDataTemplate ItemsSource="{Binding CommandsVM}" DataType="{x:Type mainvm:GameModuleViewModel}">
                    <HierarchicalDataTemplate.ItemContainerStyle>
                        <Style>
                            <Setter Property="MenuItem.Header" Value="{Binding ApplicationGame.Name}" />
                            <Setter Property="MenuItem.Icon" Value="{Binding ApplicationGame.SmallImage}" />
                        </Style>
                    </HierarchicalDataTemplate.ItemContainerStyle>
                </HierarchicalDataTemplate>
     
                <!-- Celui là est jamais utilisé ! Pourquoi ????-->
                <HierarchicalDataTemplate DataType="{x:Type mainvm:GameModuleCommandViewModel}" >
                    <HierarchicalDataTemplate.ItemContainerStyle>
                        <Style>
                            <Setter Property="MenuItem.Command" Value="{Binding Command}" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding CommandName}">
                                    <DataTrigger.Value>
                                        <mainvm:GameModuleCommand>Start</mainvm:GameModuleCommand>
                                    </DataTrigger.Value>
                                    <Setter Property="MenuItem.Header" Value="{lex:Loc StartGame}" />
                                    <Setter Property="MenuItem.Icon" Value="{StaticResource GameStartImage}" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding CommandName}">
                                    <DataTrigger.Value>
                                        <mainvm:GameModuleCommand>EditSettings</mainvm:GameModuleCommand>
                                    </DataTrigger.Value>
                                    <Setter Property="MenuItem.Header" Value="{lex:Loc EditGameSettings}" />
                                    <Setter Property="MenuItem.Icon" Value="{StaticResource GameSettingsImage}" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </HierarchicalDataTemplate.ItemContainerStyle>
                </HierarchicalDataTemplate>
            </Menu.Resources>
     
            <MenuItem ItemsSource="{Binding GamesModuleVM}" Header="{lex:Loc MenuHeader_Games}" />
        </Menu>
    Le view model d'un jeu de la liste, qui contient des view model de commandes:
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
        /// <summary>
        /// The view model of a game, in the menu.
        /// </summary>
        public class GameModuleViewModel : BaseViewModel
        {
            /// <summary>
            /// The original application game, used to create the instance.
            /// </summary>
            private IGameModule applicationGame;
     
            /// <summary>
            /// Initializes a new instance of the <see cref="GameModuleViewModel"/> class.
            /// </summary>
            /// <param name="container">The IoC container.</param>
            /// <param name="applicationGame">The application game.</param>
            public GameModuleViewModel(IUnityContainer container, IGameModule applicationGame)
                : base(container)
            {
                if (applicationGame == null)
                {
                    throw new ArgumentNullException("applicationGame");
                }
     
                this.StartCommand = new DelegateCommand(this.Start);
                this.EditSettingsCommand = new DelegateCommand(this.EditSettings);
                this.CommandsVM = new Collection<GameModuleCommandViewModel>()
                {
                    new GameModuleCommandViewModel(container, GameModuleCommand.Start, this.StartCommand),
                    new GameModuleCommandViewModel(container, GameModuleCommand.EditSettings, this.EditSettingsCommand)
                };
     
                this.ApplicationGame = applicationGame;
            }
     
            /// <summary>
            /// Gets the original application game.
            /// </summary>
            public IGameModule ApplicationGame 
            { 
                get
                {
                    return this.applicationGame;
                }
     
                private set
                {
                    if (this.applicationGame != value)
                    {
                        this.applicationGame = value;
                        this.NotifyPropertyChanged("ApplicationGame");
                    }
                }
            }
     
            /// <summary>
            /// Gets the command which will start the game.
            /// </summary>
            public ICommand StartCommand { get; private set; }
     
            /// <summary>
            /// Gets the command which will edit the game settings.
            /// </summary>
            public ICommand EditSettingsCommand { get; private set; }
     
            /// <summary>
            /// Gets all the commands of the module.
            /// </summary>
            public Collection<GameModuleCommandViewModel> CommandsVM { get; private set; }
     
            /// <summary>
            /// Starts the game.
            /// </summary>
            public void Start()
            {
            }
     
            /// <summary>
            /// Edits the settings the game.
            /// </summary>
            public void EditSettings()
            {
            }
    Le viewModel d'une commande sous menu:
    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
     
    public class GameModuleCommandViewModel : BaseViewModel
    {
            public GameModuleCommandViewModel(IUnityContainer container, GameModuleCommand commandName, ICommand command)
                : base(container)
            {
                if (command == null)
                {
                    throw new ArgumentNullException("command");
                }
     
                this.CommandName = commandName;
                this.Command = command;
            }
     
            public GameModuleCommand CommandName { get; private set; }
     
            public ICommand Command { get; private set; }
    }
    De plus, dans la console, j'ai les erreurs suivantes (4 fois des similaires):
    System.Windows.Data Error: 40 : BindingExpression path error: 'ApplicationGame' property not found on 'object' ''GameModuleCommandViewModel' (HashCode=6962099)'. BindingExpressionath=ApplicationGame.Name; DataItem='GameModuleCommandViewModel' (HashCode=6962099); target element is 'MenuItem' (Name=''); target property is 'Header' (type 'Object')

    Ca t'inspire ?

  8. #8
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 242
    Par défaut
    Yeah, enfin trouvé la solution !
    J'avais pas tout bien compris comment fonctionner les HierarchicalDataTemplate...

    J'ai quand même dû utiliser un StyleSelector, pour appliquer le bon style à chaque MenuItem.

    Voici mon code au final, au cas où ça intéresse quelqu'un...
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    <Menu>
            <Menu.Resources>
                <!-- List of the games view models -->
                <CollectionViewSource x:Key="GamesList" Source="{Binding GamesModuleVM}" />
            </Menu.Resources>
     
            <!-- First item : main menu of the application -->
            <MenuItem Header="{lex:Loc Menu_Games}" 
                      ItemContainerStyleSelector="{StaticResource GameMenuStyleSelector}">
                <MenuItem.Resources>
     
                    <!-- Style of a game MenuItem -->
                    <Style x:Key="GameMenuItemStyle" TargetType="{x:Type MenuItem}">
                        <Setter Property="MenuItem.Header" Value="{Binding ApplicationGame.Name}" />
                        <Setter Property="MenuItem.Icon" Value="{Binding ApplicationGame.SmallImage}" />
                    </Style>
     
                    <!-- Style of a command of game MenuItem (StartGame/EditSettings)-->
                    <Style x:Key="GameCommandMenuItemStyle" TargetType="{x:Type MenuItem}">
                        <Setter Property="MenuItem.Command" Value="{Binding Command}" />
                        <Style.Triggers>
                            <!-- Style of the start MenuItem-->
                            <DataTrigger Binding="{Binding CommandName}">
                                <DataTrigger.Value>
                                    <mainvm:GameModuleCommand>Start</mainvm:GameModuleCommand>
                                </DataTrigger.Value>
                                <Setter Property="MenuItem.Header">
                                    <Setter.Value>
                                        <TextBlock Text="{lex:Loc Menu_StartGame}" />
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="MenuItem.Icon" Value="{StaticResource GameStartImage}" />
                            </DataTrigger>
                            <!-- Style of the edit settings MenuItem-->
                            <DataTrigger Binding="{Binding CommandName}">
                                <DataTrigger.Value>
                                    <mainvm:GameModuleCommand>EditSettings</mainvm:GameModuleCommand>
                                </DataTrigger.Value>
                                <Setter Property="MenuItem.Header">
                                    <Setter.Value>
                                        <TextBlock Text="{lex:Loc Menu_EditGameSettings}" />
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="MenuItem.Icon" Value="{StaticResource GameSettingsImage}" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
     
                    <!-- Template of game MenuItem : each game has a submenu, with its commands -->
                    <HierarchicalDataTemplate ItemsSource="{Binding CommandsVM}" DataType="{x:Type mainvm:GameModuleViewModel}" />
                </MenuItem.Resources>
     
                <!-- MenuItems which are in the main menu of the application-->
                <MenuItem.ItemsSource>
                    <CompositeCollection>
                        <!-- List of the games -->
                        <CollectionContainer Collection="{Binding Source={StaticResource GamesList}}" />                 
                        <Separator />
     
                        <!-- Exit MenuItem -->
                        <MenuItem x:Name="ExitMenuItem" 
                                  Icon="{StaticResource ApplicationExitImage}"
                                  Command="{Binding ExitApplicationCommand}" />
                    </CompositeCollection>
                </MenuItem.ItemsSource>
            </MenuItem>
        </Menu>
    Et le code du StyleSelector
    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
     
        /// <summary>
        /// Selector of the style of the MenuItem which are in the application menu.
        /// </summary>
        public class GameMenuStyleSelector : StyleSelector
        {
            /// <summary>
            /// Selects the correct style for the MenuItem.
            /// </summary>
            /// <param name="item">The data context of the MenuItem.</param>
            /// <param name="container">The MenuItem.</param>
            /// <returns>The style to use for the MenuItem.</returns>
            public override Style SelectStyle(object item, DependencyObject container)
            {
                MenuItem menuItem = container as MenuItem;
                if (item is GameModuleViewModel)
                {
                    return menuItem.FindResource("GameMenuItemStyle") as Style;
                }
                else if (item is GameModuleCommandViewModel)
                {
                    return menuItem.FindResource("GameCommandMenuItemStyle") as Style;
                }
     
                return null;
            }
        }

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

Discussions similaires

  1. [XL-2003] Pied et en-tete de page, dans une page avec contenue dynamiques
    Par elgaied dans le forum Excel
    Réponses: 7
    Dernier message: 19/04/2012, 16h46
  2. Réponses: 0
    Dernier message: 09/04/2012, 19h43
  3. [Flex3] Affichage de Popup avec contenu dynamique
    Par Kantizbak dans le forum Flex
    Réponses: 0
    Dernier message: 20/05/2011, 10h53
  4. Liste déroulante avec contenu dynamique
    Par sdesbure dans le forum Ruby on Rails
    Réponses: 9
    Dernier message: 12/01/2008, 13h24
  5. Taille de frame avec contenu dynamique
    Par mioux dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 11/10/2007, 17h31

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