WPF - 菜单项缺失图标/图片

6

我的菜单项图标只出现在最后一个菜单项上。如果我窥探应用程序,只有最后一个菜单项的图标中有图片,在调试时,所有的菜单项都显示图标。而且,如果我添加子菜单项,菜单项上的图标会在打开子菜单后消失,最后一个子菜单会得到图标... 有什么想法吗?另外,菜单项的工具提示也无法使用。我正在使用Caliburn Micro和Fluent Ribbon控件。

        <ControlTemplate x:Key="dropDownButton">
        <ef:DropDownButton Header="{Binding DisplayName}" 
                           ItemsSource="{Binding Items}" 
                           LargeIcon="{Binding LargeIconPath}" 
                           cm:Message.Attach="ClickAction()" 
                           ef:KeyTip.Keys="{Binding KeyTip}">
            <ef:DropDownButton.ItemContainerStyle>
                <Style TargetType="MenuItem">
                    <Setter Property="Header" 
                            Value="{Binding DisplayName}"/>
                    <Setter Property="Icon">
                        <Setter.Value>
                            <Image Source="{Binding Path=IconPath}"/>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="ItemsSource" 
                            Value="{Binding Items}"/>
                    <Setter Property="cm:Message.Attach" 
                            Value="ClickAction()"/>
                    <Setter Property="ef:KeyTip.Keys" 
                            Value="{Binding KeyTip}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <ef:ScreenTip Title="{Binding DisplayName}"
                                          HelpTopic="ScreenTip help ..."
                                          Image="{Binding LargeIconPath}"
                                          Text="Text for ScreenTip"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ef:DropDownButton.ItemContainerStyle>
            <ef:DropDownButton.ToolTip>
                <ef:ScreenTip Title="{Binding DisplayName}"
                              HelpTopic="ScreenTip help ..."
                              Image="{Binding LargeIconPath}"
                              Text="Text for ScreenTip"/>
            </ef:DropDownButton.ToolTip>
        </ef:DropDownButton>

1
在我看来,类似主题的解决方案:“https://dev59.com/lG025IYBdhLWcg3wKSiP”的更好。 - Dariusz Wasacz
5个回答

9
您正在为Style中的Image控件设置Icon属性。现在,仅创建一个Style副本,因此只创建一个Image副本。现在,任何控件一次只能有一个父级。因此,当它被分配给最后一个MenuItem时,它会从以前的MenuItem控件中删除。要解决此问题,请使用Templates

请不要设置Header属性,而是设置HeaderTemplate

            <Setter Property="HeaderTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0"
                                   Source="{Binding Path=IconPath}" />
                            <TextBlock Grid.Column="1"
                                       Text="{Binding DisplayName}" />
                        </Grid>
                    </DataTemplate>
                </Setter.Value>
            </Setter>

我不确定您使用的控件工具包公开了哪些属性。但是,我确信它们一定有一个模板属性。

在这样做之后,您就不需要在样式中设置Icon属性。


尝试使用此功能时,我仍然不清楚。我收到错误消息:“'System.Windows.Controls.Grid'不是Setter上'System.Windows.Controls.HeaderedContentControl.HeaderTemplate'属性的有效值。” - no9
我的错误。你必须将它包装在“DataTemplate”中。 - decyclone

3

我成功地在 ResourceDictionary 中使用了以下条目:

<!-- Define non-shared image to avoid loss of menu icons -->
<Image x:Key="MenuIconImage" Height="16" Width="16" x:Shared="false">
    <Image.Source>
        <DrawingImage Drawing="{Binding Icon}" />
    </Image.Source>
</Image>

<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
    <Setter Property="Header" Value="{Binding DisplayName />
    <Setter Property="Icon" Value="{StaticResource MenuIconImage}" />
</Style>

这对我有用。我正在使用Textblock和矩形作为图标,而不是图像。 - RDV

0

由于某种原因,当图像是具有x:Shared = false的静态资源时,我的方法不起作用。只有最后一个菜单项显示图标。我尝试过StaticResource和DynamicResource。这是我的解决方案:

public class MenuItemIconHelper
{
    #region ImageSource Icon

    public static readonly DependencyProperty IconProperty = DependencyProperty.RegisterAttached("Icon", typeof(ImageSource), typeof(MenuItemIconHelper), new PropertyMetadata(default(ImageSource), IconPropertyChangedCallback));

    private static void IconPropertyChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var i = (MenuItem)obj;

        if (e.NewValue != null)
            i.Icon = new Image() {Source = (ImageSource)e.NewValue};
        else
            i.Icon = null;
    }

    public static void SetIcon(DependencyObject element, ImageSource value)
    {
        element.SetValue(IconProperty, value);
    }

    public static ImageSource GetIcon(DependencyObject element)
    {
        return (ImageSource)element.GetValue(IconProperty);
    }

    #endregion
}

示例:

<Style x:Key="CommandMenuItemStyle" TargetType="MenuItem">
<Setter Property="cb:MenuItemIconHelper.Icon" Value="car1.png" />
<Setter Property="Header" Value="{Binding Name}" />

我认为这比使用资源更易读,而且您不需要更改 MenuItem 的 HeaderTemplate。您还可以为 ImageSource 或 Image 实现一些缓存机制。


0

1. 添加现有文件...将图像文件添加到资源中(如果您已经有一个,请跳过此步骤)。

enter image description here

2.解决方案资源管理器中选择此图像文件。

3.生成操作更改为资源

enter image description here

最后,你可以使用简单的调用将这个图像添加到XAML中:
<Window.Resources>
    <ContextMenu x:Key="contextMenu" >
        <MenuItem Header="Restart" Name="menuItemRestart" Click="MenuItem_Click">
            <MenuItem.Icon>
                <Image Source="/Resources/restart.png"/>
            </MenuItem.Icon>
        </MenuItem>
        <Separator/>
        <MenuItem Header="Exit" Name="menuItemExit" Click="MenuItem_Click">
            <MenuItem.Icon>
                <Image Source="/Resources/window_close.png"/>
            </MenuItem.Icon>
        </MenuItem>
    </ContextMenu>
</Window.Resources>

结果: 在此输入图片描述


0

工作原理如下:

       <DataTemplate x:Key="MenuItemHeaderTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Image Grid.Column="0" Source="{Binding Path=IconPath}" />
            <Label Grid.Column="1" Content="{Binding DisplayName}" />               
        </Grid>
    </DataTemplate>


    <ControlTemplate x:Key="dropDownButton">
        <ef:DropDownButton Header="{Binding DisplayName}" 
                           ItemsSource="{Binding Items}" 
                           LargeIcon="{Binding LargeIconPath}" 
                           cm:Message.Attach="ClickAction()" 
                           ef:KeyTip.Keys="{Binding KeyTip}">
            <ef:DropDownButton.ItemContainerStyle>
                <Style TargetType="MenuItem">
                    <Setter Property="HeaderTemplate" Value="{StaticResource MenuItemHeaderTemplate}" />                                 
                    <Setter Property="ItemsSource" 
                            Value="{Binding Items}"/>
                    <Setter Property="cm:Message.Attach" 
                            Value="ClickAction()"/>
                    <Setter Property="ef:KeyTip.Keys" 
                            Value="{Binding KeyTip}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <ef:ScreenTip Title="{Binding DisplayName}"
                                          HelpTopic="ScreenTip help ..."
                                          Image="{Binding LargeIconPath}"
                                          Text="Text for ScreenTip"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ef:DropDownButton.ItemContainerStyle>
            <ef:DropDownButton.ToolTip>
                <ef:ScreenTip Title="{Binding DisplayName}"
                              HelpTopic="ScreenTip help ..."
                              Image="{Binding LargeIconPath}"
                              Text="Text for ScreenTip"/>
            </ef:DropDownButton.ToolTip>
        </ef:DropDownButton>

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