WPF, MVVM, and Menu Foreground Color

foregroundmenumvvmwpf

I'm new to both WPF and MVVM. I have searched for a good way to dynamically create menus in the MVVM parttern and I am not finding anything to my liking, so I rolled my own solution. It works, but for some reason the Foreground (text) color of the menus are sometimes (just sometimes) not correct.

I added a link for the image below.

http://img220.imageshack.us/img220/1912/badmenu.jpg (Dead Link)

My lowest submenu displays correctly with a white foreground, but its parent menus forground turned to black and is almost impossible to read. If I had hard coded the menus then the parent's forground color would be white. If I move my mouse over the parent its text will switch back to white and the submenu will become black.

Further, once I move my mouse away from the parent, all of its boolean properties IsHighlighted, IsSubmenuOpen, etc... become false, which surprising to me because I would think they should stay true. The end result is I haven't been able to solve this with a style trigger.

Here is my XAML .

<Window.Resources>
  <DataTemplate DataType="{x:Type src:ParentMenu}" >
    <Menu >
      <MenuItem Header="{Binding MenuName}" ItemsSource="{Binding ChildMenuItems}" />
    </Menu>
  </DataTemplate>

  <HierarchicalDataTemplate DataType="{x:Type src:ChildMenu}" 
                          ItemsSource="{Binding ChildMenuItems}" >
    <MenuItem Header="{Binding MenuName}" Command="{Binding Path=Command}" />
  </HierarchicalDataTemplate>

' StackOverflow is masking my end tag for Window.Resources

<DockPanel>
   <Menu DockPanel.Dock="Top" ItemsSource="{Binding Menus}" />

  <Grid>
       <!-- Add additional content here -->
  </Grid>
</DockPanel>

Both ParentMenu and ChildMenu inherit from a common class that actually holds all the menus and exposes the sub-menus through the ChildMenuItems collection. ChildMenuItems is a list of ChildMenu objects. My ViewModels expose a list of ParentMenu objects.

There are probably better ways to accomplish what I want here. Here is an example:

img132.imageshack.us/img132/4160/bettermenu.jpg (Dead Link)

Any suggestions on what I'm doing wrong and/or how to fix the display problem?

Best Answer

The problem is that your VMs automatically get wrapped in MenuItems, so you essentially have MenuItems nested as the Header of MenuItems.

You can get around this by defining a Style (and pointing to it via ItemContainerStyle) that DataBinds to your VMs (Name to Header, DelegateCommands to Command, etc.) using MenuItem as the DataType.

An example of a way you can do this is below. Note that I've dropped the HierarchicalDataTemplate in favor of an ItemContainerStyle. I also took the liberty of defining a DataTemplate for your MainViewModel as it wasn't very clear how that was data bound.

<Window.Resources>
    <DataTemplate DataType="{x:Type src:MainViewModel}">
        <ItemsControl ItemsSource="{Binding Menus}"></ItemsControl>
    </DataTemplate>
    <DataTemplate DataType="{x:Type src:ParentMenu}" >
        <Menu>
            <MenuItem Header="{Binding Name}" 
        ItemsSource="{Binding ChildMenuItems}" ItemContainerStyle="{DynamicResource ChildMenuItemStyle}" />
        </Menu>
    </DataTemplate>
    <Style x:Key="ChildMenuItemStyle" TargetType="MenuItem">
        <Setter Property="Header" Value="{Binding Name}"></Setter>
        <Setter Property="ItemsSource" Value="{Binding ChildMenuItems}"></Setter>
    </Style>
</Window.Resources>

I've also cut some of the Command binding out for simplicity, but you can add it back in as necessary.