具有默认模板和 itemTemplate 的递归菜单项

recursive menu item with default template and itemTemplate

我有一个 MenuItem 类型的 WPF 控件模板:

<Style TargetType="{x:Type MenuItem}">
    <Setter Property="Background"
            Value="Transparent" />
    <Setter Property="Cursor"
            Value="Hand" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Border Background="{TemplateBinding Background}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <ContentControl Content="{TemplateBinding Header}"
                                        Margin="5"
                                        Grid.Column="1" />
                        <Path Grid.Column="2"
                                x:Name="Indicator"
                                Data="M1,1 L1,9 9,5Z"
                                Fill="{StaticResource GlyphBrush}"
                                Margin="4"
                                Visibility="Hidden"
                                VerticalAlignment="Center" />
                        <Popup Name="PART_Popup"
                                Placement="Right"
                                IsOpen="{TemplateBinding IsSubmenuOpen}"
                                AllowsTransparency="True"
                                Grid.Column="0"
                                Grid.ColumnSpan="2"
                                HorizontalOffset="3"
                                VerticalOffset="-1">
                            <Border Background="Transparent">
                                <ContentControl Style="{StaticResource PopupContentStyle}">
                                    <ItemsPresenter/>
                                </ContentControl>
                            </Border>
                        </Popup>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked"
                                Value="true">
                        <Setter Property="Background"
                                Value="{StaticResource ButtonHoverBackgroundBrush}" />
                    </Trigger>
                    <Trigger Property="IsChecked"
                                Value="false">
                        <Setter Property="Background"
                                Value="{StaticResource BackgroundBrush}" />
                    </Trigger>
                    <Trigger Property="HasItems"
                                Value="True">
                        <Setter TargetName="Indicator"
                                Property="Visibility"
                                Value="Visible" />
                    </Trigger>
                    <Trigger Property="IsEnabled"
                                Value="False">
                        <Setter Property="Opacity"
                                Value="{StaticResource DisabledTransparency}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver"
                    Value="True">
            <Setter Property="Background"
                    Value="{StaticResource ButtonHoverBackgroundBrush}" />
        </Trigger>
    </Style.Triggers>
</Style>

如果我现在将项目添加到 MenuItem,则模板可以完美运行。但是,如果我尝试向绑定 ObservableCollection 添加项目,我 运行 就会遇到问题,因为我的 ControlTemplate 不会在任何地方使用原始 MenuItemItemTemplate

这种用法会导致问题:

<MenuItem Header="{userInterface:Translation Language}"
          ItemsSource="{Binding AvailableLanguages}">
    <MenuItem.ItemTemplate>
        <DataTemplate>
            <MenuItem Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ChangeLanguageCommand}"
                      CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Header}"
                      Header="{Binding}" />
            </DataTemplate>
    </MenuItem.ItemTemplate>
</MenuItem>

MenuItem 不使用我上面指定的 Template,而是再次采用我的默认模板。

我尝试将我的全局模板的 ItemsPresenter 更改为 ItemsControl,但它没有任何改变。

我该如何解决这个问题?

控制台,

  1. 命名你的风格 :
<Style x:Key="MenuItemStyle1" TargetType="{x:Type MenuItem}">
  1. 并且每次您打算使用它时,请使用命名资源 :
 <MenuItem Header="Hello" 
           ItemsSource="{Binding AvailableLanguages}"
           Style="{DynamicResource MenuItemStyle1}">
   <MenuItem.ItemTemplate>
     <DataTemplate>
       <MenuItem Style="{DynamicResource MenuItemStyle1}" 
                 Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ChangeLanguageCommand}"
                 CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Header}">
         <MenuItem.Header>
           <TextBlock Text="Hello" />
         </MenuItem.Header>
       </MenuItem>
     </DataTemplate>
   </MenuItem.ItemTemplate>

此致

我通过将 ItemTemplate 更改为 ItemContainerStyle 来修复此问题: 这是结果:

    <MenuItem Header="{userInterface:Translation Language}"
                ItemsSource="{Binding AvailableLanguages}">
        <MenuItem.ItemContainerStyle>
            <Style TargetType="MenuItem"
                    BasedOn="{StaticResource {x:Type MenuItem}}">
                <Setter Property="Header"
                        Value="{Binding Name}" />
                <Setter Property="Command"
                        Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ChangeLanguageCommand}" />
                <Setter Property="CommandParameter"
                        Value="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}" />
                <Setter Property="IsChecked"
                        Value="{Binding IsSelected}">
                </Setter>
            </Style>
        </MenuItem.ItemContainerStyle>
    </MenuItem>

初始 ItemTemplate 的问题是 MenuItem 内部使用 MenuItem 作为项目容器模板。这导致 MenuItem 位于 MenuItem 内,其中 CommandCommandProperty 位于内部 MenuItem 而样式位于外部 MenuItem.这导致我的 Command 出现问题,因为外部 MenuItem 已经消耗了 Click.

现在使用 ItemContainerStyle setters 应用到正确的 MenuItem 而使用 BasedOn 属性 则采用全局 MenuItem 风格的所有 Setters .