【问题标题】:Why only the last menu item has icon?为什么只有最后一个菜单项有图标?
【发布时间】:2020-07-14 20:55:05
【问题描述】:

在 WPF 中,我以编程方式向控件添加上下文菜单。

    var contextMenu = new ContextMenu();
    contextMenu.Items.Add(new MenuItem { Header = "Copy All", Icon  = FindResource("CopyImage") });
    contextMenu.Items.Add(new MenuItem { Header = "Copy All with Headers", Icon = FindResource("CopyImage") });
    contextMenu.Items.Add(new MenuItem { Header = "Copy Selected", Icon = FindResource("CopyImage") });
    contextMenu.Items.Add(new MenuItem { Header = "Copy Selected with Headers", Icon = FindResource("CopyImage") });

CopyImage 在我的应用程序资源中定义。

<Image x:Key="CopyImage" Source="../Images/copy.png"/>

在运行时,只有最后一个菜单项显示图标。其他三个菜单项没有。

有人对此行为有解释吗?

【问题讨论】:

  • 你能说明CopyImage的定义吗?
  • 嗨,@NathanA,根据您的要求添加。谢谢。

标签: c# wpf


【解决方案1】:

看看这个article

它说明图像一次只能在一个地方使用。这可以解释为什么它只出现在您在代码中所做的最新分配上。而是定义一个 BitmapImage,然后使用 BitmapImage 作为每个菜单项的源创建一个新图像。

来自其他文章:

为此,请在某处创建一个 BitmapSource 作为资源:

<BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" />

然后,在您的代码中,使用类似:

<Image Source="{StaticResource MyImageSource}" />

【讨论】:

  • 我也有同样的问题。我试图在Icon 属性中放置TextBox 而不是图像...同样的问题。
  • 这并不能真正解决问题,因为它假设您使用的是位图。我正在使用一个带有边框的矩形,似乎唯一真正的方法是创建一个转换器,该转换器为菜单中的每个项目返回一个新的 UI 元素对象。这样你也可以让转换器根据绑定返回不同的类型。
【解决方案2】:

每个 UI 元素只能放置在可视化树中的一个位置。您不能在多个 MenuItem 上使用相同的 Image 控件。您需要为每个 MenuItem 创建单独的图像控件。否则每次你将它分配给一个新的 MenuItem 时,你只是将它从一个移动到另一个。

<Image x:Key="CopyImage1" Source="../Images/copy.png"/>
<Image x:Key="CopyImage2" Source="../Images/copy.png"/>
<Image x:Key="CopyImage3" Source="../Images/copy.png"/>
<Image x:Key="CopyImage4" Source="../Images/copy.png"/>

var contextMenu = new ContextMenu();
    contextMenu.Items.Add(new MenuItem { Header = "Copy All", Icon  = FindResource("CopyImage1") });
    contextMenu.Items.Add(new MenuItem { Header = "Copy All with Headers", Icon = FindResource("CopyImage2") });
    contextMenu.Items.Add(new MenuItem { Header = "Copy Selected", Icon = FindResource("CopyImage3") });
    contextMenu.Items.Add(new MenuItem { Header = "Copy Selected with Headers", Icon = FindResource("CopyImage4") });

【讨论】:

    【解决方案3】:

    试试这个,Icon = new BitmapImage(new Uri("images/copy.png", UriKind.Relative))

    var contextMenu = new ContextMenu();
    contextMenu.Items.Add(new MenuItem { Header = "Copy All", Icon  = new BitmapImage(new Uri("images/copy.png", UriKind.Relative)) });
    contextMenu.Items.Add(new MenuItem { Header = "Copy All with Headers", Icon = new BitmapImage(new Uri("images/copy.png", UriKind.Relative)) });
    contextMenu.Items.Add(new MenuItem { Header = "Copy Selected", Icon = new BitmapImage(new Uri("images/copy.png", UriKind.Relative)) });
    contextMenu.Items.Add(new MenuItem { Header = "Copy Selected with Headers", Icon = new BitmapImage(new Uri("images/copy.png", UriKind.Relative)) });
    

    【讨论】:

      【解决方案4】:

      所有答案都有帮助。这是我根据@NathanA 的指针最终做的事情:

      var contextMenu = new ContextMenu();
      contextMenu.Items.Add(new MenuItem
      {
          Header = "Copy All",
          Icon = new Image {Source = FindResource("CopyImageSource") as ImageSource}
      });
      contextMenu.Items.Add(new MenuItem
      {
          Header = "Copy All with Headers",
          Icon = new Image {Source = FindResource("CopyImageSource") as ImageSource}
      });
      contextMenu.Items.Add(new MenuItem
      {
          Header = "Copy Selected",
          Icon = new Image {Source = FindResource("CopyImageSource") as ImageSource}
      });
      contextMenu.Items.Add(new MenuItem
      {
          Header = "Copy Selected with Headers",
          Icon = new Image {Source = FindResource("CopyImageSource") as ImageSource}
      });
      

      资源字典中的这个:

      <BitmapImage x:Key="CopyImageSource" UriSource="../Images/copy.png"/>
      

      【讨论】:

        【解决方案5】:

        对于适用于任何类型且保持灵活的解决方案,我使用了转换器。

        这使您可以灵活地根据结果返回完全不同的组件。就我而言,虽然我只是绑定到一个十六进制值。

        XAML

        <ContextMenu d:DataContext="{d:DesignInstance Type=applicantDetails:ApplicantSelections}" x:Key="HeatContextMenu" DataContext="{x:Static applicantDetails:ApplicantSelections.StaticRefApplicantSelections}" ItemsSource="{Binding TodoHeats}">
                            <ContextMenu.ItemContainerStyle>
                                <Style TargetType="MenuItem">
                                    <Setter Property="Icon" Value="{Binding HexColour, Converter={StaticResource HeatMenuItemConverter}}" >
                                    </Setter>
                                </Style>
                            </ContextMenu.ItemContainerStyle>
                            <ContextMenu.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Description}" d:DataContext="{d:DesignInstance Type=todoManager:TodoHeat}"></TextBlock>
                                </DataTemplate>
                            </ContextMenu.ItemTemplate>
                        </ContextMenu>
        

        转换器

        class HeatMenuItemConverter : IValueConverter
        {
            /// <summary>
            /// Converts the specified value.
            /// </summary>
            /// <param name="value">The value.</param>
            /// <param name="targetType">Type of the target.</param>
            /// <param name="parameter">The parameter.</param>
            /// <param name="culture">The culture.</param>
            /// <returns></returns>
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                Border border = new Border();
                border.BorderBrush = Brushes.Black;
                Rectangle rectangle = new Rectangle();
                border.Child = rectangle;
                rectangle.Height = 50;
                rectangle.Width = 50;
        
                try
                {
                    if (value != null && value is string hexCode)
                    {
                        rectangle.Fill = (SolidColorBrush)new BrushConverter().ConvertFromString(hexCode);
                    }
                }
                catch (Exception e)
                {
                    // ignored
                }
        
                return border;
            }
        
            /// <summary>
            /// Converts it back.
            /// </summary>
            /// <param name="value">The value.</param>
            /// <param name="targetType">Type of the target.</param>
            /// <param name="parameter">The parameter.</param>
            /// <param name="culture">The culture.</param>
            /// <returns>Converted Value</returns>
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return value;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-25
          • 1970-01-01
          • 2014-02-15
          • 2021-05-18
          相关资源
          最近更新 更多