为什么只有最后一个菜单项有图标?

10
在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 的定义吗? - Nathan A
嗨,@NathanA,已按照您的要求添加。谢谢。 - Igor Pashchuk
5个回答

8
请查看这篇文章
文章解释了一个图片只能在一个地方使用的原因,这也可以解释为什么它只出现在你最近在代码中创建的任务上。相反,应该定义一个BitmapImage,然后为每个菜单项创建一个新的图像,并将BitmapImage作为源。
从其他文章中得到以下信息:
要做到这一点,请将BitmapSource作为资源创建在任何位置:
<BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" />

接下来,在你的代码中使用以下方式:

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

我有同样的问题。我尝试在“图标”属性中放置一个TextBox而不是一个图像...但是出现了相同的问题。 - Shachar Har-Shuv
这并没有真正解决问题,因为它假设您正在使用位图。我正在使用一个带有边框的矩形,似乎唯一真正的方法是创建一个转换器,为菜单中的每个项目返回一个新的UI元素对象。这样,您还可以使转换器根据绑定返回不同类型。 - kenjara

4

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

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

0

所有答案都很有帮助。根据@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"/>

-1
为了实现适用于任何类型且保持灵活性的解决方案,我使用了一个转换器。
这使您可以根据结果返回完全不同的组件。但在我的情况下,我只绑定到一个十六进制值。
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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接