bic
bic

Reputation: 2281

MenuItem style with icon creates only one icon

Im having a problem rendering icons for a dynamic menu which uses viewmodels as an ItemsSource.
The solution I've used is outlined here MVVM Dynamic Menu UI from binding with ViewModel

The basic layout is as follows

<Grid>
  <Grid.Resources>
    <HierarchicalDataTemplate DataType="{x:Type ViewModels:HeaderedItemViewModel}"
        ItemsSource="{Binding Path=Children}">
      <ContentPresenter RecognizesAccessKey="True"></ContentPresenter>
    </HierarchicalDataTemplate>
    <Style TargetType="{x:Type MenuItem}">
      <Setter Property="Header" Value="{Binding Path=Header}" />
      <Setter Property="InputGestureText" Value="{Binding Path=InputGestureText}" />
      <Setter Property="Command" Value="{Binding Path=Command}" />
      <Setter Property="Icon">
        <Setter.Value>
          <Image Source="{Binding Path=Icon}" Height="16px" Width="16px" />
        </Setter.Value>
      </Setter>
    </Style>
  </Grid.Resources>
  <Menu Grid.Row="0" ItemsSource="{Binding Path=Shell.Navigation.Menus}" />
</Grid>

In the above style the binding 'Icon' is 'ImageSource'. This is set up as follows.

        BitmapImage image = null;

        if (!string.IsNullOrEmpty(imagePath))
        {
            image = new BitmapImage(new Uri(imagePath, UriKind.Relative));
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
        }
        var menu = new HeaderedItemViewModel
                       {
                           Header = header,
                           InputGestureText = inputGesture,
                           ImagePath = imagePath,
                           Icon = image,
                           Command = command,
                           IsEnabled = isEnabled
                       };

The problem I'm having is with the icons.
It seems only one icon will render at a time? Heres what I mean.

enter image description here

And opening the dropdown menu ...

enter image description here

As soon as another image is rendered the first one disappears? In other words only the last image is visible. This happens with all the images in the menu. Any ideas?

Upvotes: 29

Views: 7951

Answers (2)

user3615613
user3615613

Reputation: 71

I've searched various responses and the x:Shared="false" thing is surely helping but you need also to setup all properly to make it sure it works and it took me a bit to find the proper solution. This is how I've make it working on my side

        <ContextMenu ItemsSource="{Binding MenuElements}">
            <ContextMenu.Resources>
                <ControlTemplate x:Key="MenuSeparatorTemplate">
                    <Separator />
                </ControlTemplate>
                <Image
                    x:Key="MenuIcon"
                    Width="16"
                    Height="16"
                    x:Shared="False"
                    Source="{Binding Icon}" />
            </ContextMenu.Resources>
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding Name}" />
                    <Setter Property="ItemsSource" Value="{Binding Childs}" />
                    <Setter Property="Command" Value="{Binding Run}" />
                    <Setter Property="Icon" Value="{StaticResource MenuIcon}" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsSeparator}" Value="true">
                            <Setter Property="Template" Value="{StaticResource MenuSeparatorTemplate}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContextMenu.ItemContainerStyle>
        </ContextMenu>

This way I've been able to make my context menu to dynamically load the icons depending on the input.

Upvotes: 1

PawelSt
PawelSt

Reputation: 846

Add x:Shared=false for your Icon value. To do that you should declare Image in resources:

<Grid>
  <Grid.Resources>

   <Image x:Key="imgCTX" x:Shared="false"
         Source="{Binding Path=Icon}" Height="16px" Width="16px"/>
    <HierarchicalDataTemplate DataType="{x:Type ViewModels:HeaderedItemViewModel}"
        ItemsSource="{Binding Path=Children}">
      <ContentPresenter RecognizesAccessKey="True"></ContentPresenter>
    </HierarchicalDataTemplate>
    <Style TargetType="{x:Type MenuItem}">
      <Setter Property="Header" Value="{Binding Path=Header}" />
      <Setter Property="InputGestureText" Value="{Binding Path=InputGestureText}" />
      <Setter Property="Command" Value="{Binding Path=Command}" />
      <Setter Property="Icon" Value="{StaticResource imgCTX}" />
    </Style>
  </Grid.Resources>
  <Menu Grid.Row="0" ItemsSource="{Binding Path=Shell.Navigation.Menus}" />
</Grid>

Upvotes: 47

Related Questions