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

时间:2015-08-17 16:07:45

标签: c# wpf

在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"/>

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

enter image description here

有没有人对此行为有解释?

5 个答案:

答案 0 :(得分:8)

看看这个article

它解释了图像一次只能在一个地方使用。这可以解释为什么它最终只会出现在代码中的最新作业。相反,定义一个BitmapImage,然后使用BitmapImage作为每个菜单项的源来创建一个新图像。

来自其他文章:

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

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

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

的内容
<Image Source="{StaticResource MyImageSource}" />

答案 1 :(得分:4)

每个UI元素只能放置在可视树中的一个位置。您无法在多个MenuItem上使用相同的Image控件。您需要为每个MenuItem创建单独的Image控件。否则,每次将其分配给新的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") });

答案 2 :(得分: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)) });

答案 3 :(得分: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"/>

答案 4 :(得分:-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;
    }
}