【问题标题】:MenuItem style with icon creates only one icon带有图标的 MenuItem 样式只创建一个图标
【发布时间】:2011-09-04 20:58:33
【问题描述】:

我在为使用视图模型作为 ItemsSource 的动态菜单呈现图标时遇到问题。
我使用的解决方案在此处概述 MVVM Dynamic Menu UI from binding with ViewModel

基本布局如下

<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>

在上述样式中,绑定“Icon”是“ImageSource”。设置如下。

        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
                       };

我遇到的问题是图标。
似乎一次只会渲染一个图标?这就是我的意思。

然后打开下拉菜单...

一旦渲染另一张图像,第一张图像就会消失?换句话说,只有最后一个图像是可见的。菜单中的所有图像都会发生这种情况。有什么想法吗?

【问题讨论】:

  • 一个问题:如何设置实际输入绑定,绑定到 InputGestureText 不会设置实际输入绑定。
  • 我目前没有使用输入绑定。这可能会进一步帮助您。 blogs.msdn.com/b/llobo/archive/2009/10/29/…。通过扩展命令类,您可以将它们映射到来自 ViewModel 的输入 bingings 集合。
  • @bitbonk:是的,手势按照上面的定义绑定。我有一个名为 NavigationViewModel 的类,它创建和初始化所有菜单和工具栏。这些都派生自一个名为 HeaderItemViewModel 的类。这意味着我可以为同样出现在工具栏中的菜单项重用实例。这能回答你的问题吗?

标签: wpf mvvm


【解决方案1】:

为您的图标值添加 x:Shared=false。 为此,您应该在资源中声明 Image:

<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>

【讨论】:

  • 效果很好,谢谢。一个小问题是在图像资源中使用高度和宽度。这会导致顶级菜单展开,即使它们没有图像。我想我可以重新缩放图像并完成它。知道如何仅在实际可用图像时应用高度和宽度吗?
  • 我想我可以将这些添加到视图模型并直接绑定它们,这可能是最简单的方法。
  • 另外,你的答案有错别字, 应该是
  • 您如何防止顶级菜单项根据底层菜单项调整大小?
  • 拯救了我的一天。谢谢
【解决方案2】:

我已经搜索了各种回复,x:Shared="false" 肯定会有所帮助,但您还需要正确设置所有内容以确保其正常工作,我花了一些时间才找到合适的解决方案。这就是我让它在我身边工作的方式

        <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>

通过这种方式,我可以让上下文菜单根据输入动态加载图标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 2016-11-02
    • 2023-01-12
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多