使用 ItemContainerStyle 时如何在 ContextMenu 的 MenuItem 中设置图标

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

所以我有一个 Context Menu 和一个 MenuItem 在里面,它分成一个名字列表:

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

现在上面的代码可以运行文件并显示我的姓名列表。现在我想使用 Pack URI 在每个名称旁边添加一个图标。所以从 this question 我可以看到最好的方法是模板化 Header 所以我首先尝试像问题

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

但这给了我错误:

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

所以我经过一些研究后尝试了:

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

但是现在我的名字都是ControlTemplate,没有图标显示...

如何通过 ItemContainerStyle 将图标添加到上下文菜单的菜单项?

编辑

我试过:

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

我得到了图标渲染,但只针对菜单中的最后一项?

问题是您不能在多个地方使用一种视觉对象。您可以使用 HeaderTemplate 代替 Header,但使用 DataTemplate 代替 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>

请注意,此解决方案会将图标放在 MenuItem 的内容部分,而不是图标。另一种解决方案是将 MenuItemIcon 属性 设置为另一个 Setter 但在这种情况下 Image 需要 将 Resourcex:Shared 设置为 false 分开,否则您将遇到同样的问题,即只有最后一项有图标。

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