WPF - No MenuItem Icon / Image

Im getting the MenuItem icon appears only in the last menuItem element. If I snoop the application only the last menuItem has the image in the icon, and if I debug all MenuItems, the image appears in the icon. Also, if I add a submenuItem the icon on the menuItem disappears as soon as I open the submenu and the last submenu gets the icon ... Any idea? PS: also tooltips on the menu item do not work. Im using calibration micro- and running tape 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> 
+4
source share
4 answers

You set the Icon property of the Image control to Style . Now only one copy of Style and thus only one copy of Image . Now any control can have only one parent at a time. Therefore, when it is assigned to the last MenuItem , it is removed from previous MenuItem controls. To fix this, use Templates .

Instead of setting the Header property, set the 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 which properties are exposed using the management tools you use. But I am sure that they should have a template property.

After that, you do not need to set the Icon property in the style.

+7
source

It works as follows:

  <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> 
0
source

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> 
0
source

For some reason, the approach where Image is a static resource with x: Shared = false does not work for me. Only the last menu item shows an icon. I have 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 } 

Example:

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

I believe this is more readable than using the resource, and you do not need to change the MenuItem HeaderTemplate. You can also implement some caching mechanism for ImageSource or Image.

0
source

All Articles