Comment puis-je lier une ObservableCollection des ViewModels à un MenuItem?
Quand je lier les Éléments du Menu avec une ObservableCollection, seul le "intérieure" de la MenuItem est cliquable:
le texte d'alt http://tanguay.info/web/external/mvvmMenuItems.png
Dans mon Vue j'ai ce menu:
<Menu>
<MenuItem
Header="Options" ItemsSource="{Binding ManageMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
</Menu>
Puis-je lier avec ce DataTemplate:
<DataTemplate x:Key="MainMenuTemplate">
<MenuItem
Header="{Binding Title}"
Command="{Binding DataContext.SwitchPageCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"
Background="Red"
CommandParameter="{Binding IdCode}"/>
</DataTemplate>
Depuis chaque ViewModel dans l'ObservableCollection ManageMenuPageItemViewModels a une propriété Titre et IdCode, le code ci-dessus fonctionne très bien à première vue.
CEPENDANT, le problème est que le MenuItem dans le DataTemplate est en fait à l'intérieur de un autre MenuItem (comme si c'est lié à deux reprises) ainsi que dans les au-dessus de DataTemplate avec Background="Rouge" il y a un boîte Rouge à l'intérieur de chaque élément de menu et uniquement cette zone peut être cliqué, pas l'ensemble de la zone élément de menu lui-même (par exemple, si l'utilisateur clique sur la zone où le champ est ou vers la droite ou la gauche de l'intérieur de la zone cliquable, puis rien ne se passe, qui, si vous n'avez pas de couleur est très déroutant.)
Quelle est la bonne manière de lier MenuItems à une ObservableCollection des ViewModels, de sorte que l'ensemble de la zone à l'intérieur de chaque MenuItem est cliquable?
Mise à JOUR:
J'ai donc fait les modifications suivantes sont fondées sur des conseils ci-dessous et avoir cette:
le texte d'alt http://tanguay.info/web/external/mvvmMenuItemsYellow.png
Je n'ai qu'un TextBlock à l'intérieur de mon DataTemplate, mais je ne peux toujours pas "la couleur de l'ensemble de la MenuItem" mais juste le TextBlock:
<DataTemplate x:Key="MainMenuTemplate">
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
Et j'ai mis de la liaison de Commande dans le Menu.ItemContainerStyle mais ils n'ont pas le feu maintenant:
<Menu DockPanel.Dock="Top">
<Menu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Command" Value="{Binding DataContext.SwitchPageCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"/>
<Setter Property="CommandParameter" Value="{Binding IdCode}"/>
</Style>
</Menu.ItemContainerStyle>
<MenuItem
Header="MVVM" ItemsSource="{Binding MvvmMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
<MenuItem
Header="Application" ItemsSource="{Binding ApplicationMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
<MenuItem
Header="Manage" ItemsSource="{Binding ManageMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
</Menu>
OriginalL'auteur Edward Tanguay | 2009-07-01
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé en utilisant MVVM avec MenuItems être très difficile. Le reste de mon application utilise DataTemplates pour lier la Vue avec le ViewModel, mais qui ne semble tout simplement pas travailler avec des Menus en raison de précisément les raisons que vous avez décrit. Voici comment j'ai finalement résolu. Mon point de Vue, ressemble à ceci:
Si vous remarquez, j'ai défini une interface appelée IMenuItem, qui est le ViewModel pour un MenuItem. Voici le code pour que:
Avis que le IMenuItem définit IEnumerable, ce qui est la façon dont vous obtenez les sous-menus. Aussi, le IsSeparator est un moyen de définir des séparateurs dans le menu (une autre difficile petit truc). Vous pouvez voir dans le code xaml comment il utilise un DataTrigger de changer le style de l'existant séparateur de style si IsSeparator est vrai. Voici comment MainViewModel définit le MainMenu propriété (que la vue se lie à l'):
Cela semble bien fonctionner. Je suppose que vous pourriez utiliser une ObservableCollection pour le MainMenu. Je suis en fait à l'aide de la MEF pour composer le menu de pièces, mais après que les éléments eux-mêmes sont statiques (même si les propriétés de chaque élément de menu ne sont pas). J'utilise aussi un AbstractMenuItem classe qui implémente IMenuItem et est d'une aide de la classe à instancier les éléments de menu dans les différentes parties.
Mise à JOUR:
Concernant votre problème de couleur, ne ce fil aider?
J'ai très semblable à la conception et la tout fonctionne sauf pour l'affichage de la séparation. Si je change le template <Label>Séparateur</Label> puis je vois "Séparateur" où un séparateur doit être. Mais quand j'essaie d'utiliser le modèle comme dans votre réponse, rien n'est montré. J'ai essayé <Séparateur BorderThickness="100" BorderBrush="Black"></Séparateur> et puis le séparateur est visible, mais je veux le style par défaut de la largeur de définir de façon dynamique par la largeur du menu. Suis-je censé définir SeparatorStyleKey quelque part? J'ai cherché en ligne, mais ne pouvait pas trouver quelque chose qui a aidé... Merci!
OriginalL'auteur Scott Whitlock
Ne pas mettre le
MenuItem
dans leDataTemplate
. LeDataTemplate
définit la contenu de laMenuItem
. Au lieu de cela, spécifiez étrangères propriétés de laMenuItem
via leItemContainerStyle
:Aussi, jetez un oeil à
HierarchicalDataTemplate
s.Merci, c'est exactement que je cherchais. Fonctionne très bien. Merci!
+1 - HierarchicalDataTemplates faire tout ce problème presque trivial.
OriginalL'auteur Kent Boogaart
Voici comment j'ai fait mes menus. Il peut ne pas être exactement ce dont vous avez besoin, mais je pense que c'est assez proche.
TopMenuViewModel est une collection de menus qui apparaissent sur la barre de menu. Ils contiennent chacun l'MenuName qui sera affiché et une collection appelée SubMenuItems que je me suis mis à la ItemsSource.
Je contrôle la façon dont le SubMenuItems sont affichés par le style SumMenuItemStyle. Chaque SubMenuItem a son propre MenuName propriété, propriétés de Commande de type ICommand, et éventuellement une autre collection de SubMenuItems.
Le résultat est que je suis capable de stocker tout mon menu de l'information dans une base de données et de passer dynamiquement les menus sont affichés lors de l'exécution. L'ensemble de la menuitem zone est cliquable et s'affiche correctement.
Espère que cette aide.
OriginalL'auteur RB Davidson
Suffit de faire votre DataTemplate pour être un TextBlock (ou peut-être une pile du panneau avec une icône et d'un TextBlock).
Modifier la ItemContainerStyle
modifié en conséquence ci-dessus, posté capture d'écran, ne fonctionne toujours pas 🙁
Hmmm, vous pouvez avoir à lier à la balise du TextBlock, puis à rédiger un OnApplyTemplate gestionnaire ou quelque chose et à pied de l'arbre en arrière jusqu'à la MenuItem. Super hacky et non WPF y, mais parfois vous devez.
Merci, l'édition de la ItemContainerStyle a fonctionné pour moi. (Utilisé Kent Boogaart l'exemple.)
OriginalL'auteur Paul Betts