4

I want to bind icons to the MenuItem controls where these items are dynamically created. I tried to set the x:Shared attribute to False but always only the last item has icon.

Here is my style for the MenuItems ItemContainerStyle code:

<Window.Resources>
    <Style TargetType="{x:Type MenuItem}" x:Key="MenuItemStyle" x:Shared="False">
        <Setter Property="Icon">
            <Setter.Value>
                <Image Source="{Binding IconSource}" />
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

And the MenuItem definition:

<MenuItem Header="Workspaces" ItemsSource="{Binding WorkspaceItems}" Icon="{StaticResource BranchIcon}" ItemContainerStyle="{StaticResource MenuItemStyle}" />

I have already tried to set this Shared attribute on the Image control but no luck.

Any suggestion?

Panthesilea
  • 123
  • 9
  • Do you get any binding errors/warnings in the Visual Studio Output window? – haindl Oct 14 '16 at 08:44
  • No, it's compilable. And it works only for one item. I know that this happens when style always changes position because it can have only one parent. But everyone says that it can be modified by the x:Shared attribute. Maybe I missed something, I don't know why it doesn't work. – Panthesilea Oct 14 '16 at 08:53

1 Answers1

6

You are almost there!

First of all: don't be confuse by Template vs Style.

When you are setting Icon property to an Image control, only one copy is created. As a control can have only one parent, it is removed from the previous parent each time it's re-assigned.

That's why you see only one icon.

You have 2 solutions for what you want:

  • use datatemplate instead, and redefine the whole Template of a MenuItem
  • use a style with a shared image component (what you tried to achieve)

In your example the only error is that the Shared attribute should be false on the Image resource, not on the whole style. This should work:

<Window.Resources>
    <Image x:Key="MenuIconImage" x:Shared="false" Source="{Binding IconSource}"/>

    <Style TargetType="{x:Type MenuItem}" x:Key="MenuItemStyle" BasedOn="{StaticResource {x:Type MenuItem}}">
        <Setter Property="Icon" Value="{StaticResource MenuIconImage}">
        </Setter>
    </Style>
</Window.Resources>

Hope it helps.

Community
  • 1
  • 1
Ouarzy
  • 3,015
  • 1
  • 16
  • 19
  • Thanks! I tried the shared image component and it works :) – Panthesilea Oct 14 '16 at 11:30
  • 1
    I followed this exactly and couldn't get it to work for me (icon still only showing on the last/bottom menu item). I've tried using MaterialDesign.PackIcon as the MenuItem.Icon and also a plain image. Any ideas? – Peter May 13 '19 at 21:39
  • @Peter I had to add an `x:Shared="false"` attribute to my MenuIconImage in my ResourceDictionary (in `App.xaml`), so the whole line looks like `` – Victor Wilson Feb 04 '20 at 20:45
  • In order to get the MaterialDesign icons to appear (and not just the last one), I had to use a converter on the Binding, which returns the PackIconKind. – h4le5torm Feb 27 '20 at 21:05