递归菜单项,使用默认模板和项目模板。

8

我有一个针对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,但没有任何改变。

我该如何解决这个问题?

2个回答

2
我通过将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,setter 将应用于正确的 MenuItem,而使用 BasedOn 属性将获取全局 MenuItem 样式的全部 Setter。


1

控制台,

  1. 命名你的样式 :
<Style x:Key="MenuItemStyle1" TargetType="{x:Type MenuItem}">

2. 每次使用时,请使用命名资源
 <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>

致敬


我尝试了这个,但是没有效果,全局的 MenuItem 模板仍然没有在任何地方使用项模板。 - quadroid
当然,就像上面的帖子一样,你会将样式分配给两个菜单,对吧?我刚刚发布了我的项目。我已经让它工作了(即使它看起来非常丑陋)。http://1drv.ms/1GWDPUm - Emmanuel DURIN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接