开发者

MenuItem style with icon creates only one icon

开发者 https://www.devze.com 2023-03-09 18:53 出处:网络
Im having a problem rendering icons for a dynamic menu which uses viewmodels as an ItemsSource. The solution I\'ve used is outlined here

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>
    &l开发者_开发百科t;/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.

MenuItem style with icon creates only one icon

And opening the dropdown menu ...

MenuItem style with icon creates only one icon

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?


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>


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消