Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set an Icon in a ContextMenu's MenuItem when using ItemContainerStyle

So I have a Context Menu And a MenuItem in it which breaks out into a list of names:

<ContextMenu>
    <MenuItem Header="Set As Default For" ItemsSource="{Binding Source={StaticResource Names}}">
       <MenuItem.ItemContainerStyle>
           <Style TargetType="MenuItem">
                <Setter Property="Header" Value={Binding Name}/>
                <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}, Path=DataContext.DoSomething}" />
                <Setter Property="CommandParameter" Value="{Binding }" />
            </Style>
         </MenuItem.ItemContainerStyle>
     </MenuItem>
</ContextMenu>

Now the above code works file and displays my list of names. Now I would like to add an Icon next to each Name using a Pack URI.. So from this question I can see the best way to do it is to template the Header so I tried that first like the question

<ContextMenu>
    <MenuItem Header="Set As Default For" ItemsSource="{Binding Source={StaticResource Names}}">
       <MenuItem.ItemContainerStyle>
           <Style TargetType="MenuItem">
                <Setter Property="Header">
                    <Setter.Value>
                         <StackPanel>
                               <Image Width="20" Height="20" Source="/MyProj;component/Resources/MyImg.png" />
                              <ContentPresenter Content="{Binding Name}" />
                          </StackPanel>
                     </Setter.Value>
                 </Setter>
                 <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}, Path=DataContext.DoSomething}" />
                 <Setter Property="CommandParameter" Value="{Binding }" />
            </Style>
         </MenuItem.ItemContainerStyle>
     </MenuItem>
</ContextMenu>

but this gave me the error:

Specified element is already the logical child of another element. Disconnect it first.

So I after some research I tried:

<ContextMenu>
    <MenuItem Header="Set As Default For" ItemsSource="{Binding Source={StaticResource Names}}">
       <MenuItem.ItemContainerStyle>
           <Style TargetType="MenuItem">
                <Setter Property="Header">
                    <Setter.Value>
                         <ControlTemplate>
                             <StackPanel>
                                   <Image Width="20" Height="20" Source="/MyProj;component/Resources/MyImg.png" />
                                    <ContentPresenter Content="{Binding Name}" />
                              </StackPanel>
                           </ControlTemplate>
                     </Setter.Value>
                 </Setter>
                 <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}, Path=DataContext.DoSomething}" />
                 <Setter Property="CommandParameter" Value="{Binding }" />
            </Style>
         </MenuItem.ItemContainerStyle>
     </MenuItem>
</ContextMenu>

But now all my names are ControlTemplate and no icon is displayed...

How do I add an icon to a Context Menu's Menu Item through ItemContainerStyle?

EDIT

I've tried:

   <Setter Property="Header" Value="{Binding Name}"/>
   <Setter Property="Icon">
       <Setter.Value>
           <Image Width="20" Height="20" Source="/MyProj;component/Resources/MyImg.png" />
       </Setter.Value>
    </Setter>

And I get an icon rendering but only for the last item in my menu?

like image 411
User1 Avatar asked Mar 17 '15 11:03

User1


1 Answers

The problem is that you cannot use one visual in more then one place. You can do it either by using HeaderTemplate instead of Header, but use DataTemplate instead of ControlTemplate

<Style TargetType="MenuItem">
   <Setter Property="HeaderTemplate">
      <Setter.Value>
         <DataTemplate>
            <StackPanel>
               <Image Width="20" Height="20" Source="/MyProj;component/Resources/MyImg.png" />
               <ContentPresenter Content="{Binding Name}" />
            </StackPanel>
         </DataTemplate>
      </Setter.Value>
   </Setter>
   <!-- other setters -->
</Style>

Note that this solution will put icon in the content part of MenuItem, not the icon. Another solution is to set Icon property of MenuItem as another Setter but in this case Image needs to be separate Resource with x:Shared set to false otherwise you'll end up with the same problem where only last item has an icon.

<ContextMenu>
   <ContextMenu.Resources>
      <Image Width="20" Height="20" Source="/MyProj;component/Resources/MyImg.png" x:Key="myMenuIcon" x:Shared="False" />
   </ContextMenu.Resources>
   <MenuItem Header="Set As Default For" ItemsSource="{Binding Source={StaticResource Names}}">
      <MenuItem.ItemContainerStyle>
         <Style TargetType="{x:Type MenuItem}">
            <Setter Property="Header" Value="{Binding Name}"/>
            <Setter Property="Icon" Value="{StaticResource myMenuIcon}"/>
         </Style>
      </MenuItem.ItemContainerStyle>
   </MenuItem>
</ContextMenu>
like image 165
dkozl Avatar answered Oct 23 '22 13:10

dkozl