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.
source share