问题
Im getting menuItem icon appearing only on last menuItem. If i snoop the app only last menuItem has image in icon, while if i debug all MenuItems appear to have image in icon. Also if i add submenuItem the icon on menuItem dissapears once i open submenus and the last submenu gets the icon... Any idea? PS: also tooltips on menu item dont work. Im using caliburn micro and fluent ribbon controls.
<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:
You are setting Icon
property to an Image
control in Style
. Now, only one copy of Style
is created and thus, only one copy of Image
is created. Now, any control can have only one parent at a time. So, when it is assigned to last MenuItem
, it is removed from previous MenuItem
controls. To fix this, use Templates
.
Instead of setting Header
property, set 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>
I'm not sure of what properties are exposed by the control toolkit you are using. But, I'm sure they must have a template property.
After doing this, you don't need to set Icon
property in style.
回答2:
I successfully use the following entries in a 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>
回答3:
Works like this:
<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>
回答4:
For some reason approach when Image is static resource with x:Shared = false doesn't work for me. Only last menu item shows icon. I've tried both StaticResource and DynamicResource. Here is my solution:
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
}
Sample:
<Style x:Key="CommandMenuItemStyle" TargetType="MenuItem">
<Setter Property="cb:MenuItemIconHelper.Icon" Value="car1.png" />
<Setter Property="Header" Value="{Binding Name}" />
I consider it to be more readable than using resource and you don't need to change MenuItem's HeaderTemplate. You can also implement some caching mechanism for ImageSource or Image.
来源:https://stackoverflow.com/questions/4398954/wpf-menuitem-missing-icon-image