具有默认模板和 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
不会在任何地方使用原始 MenuItem
的 ItemTemplate
。
这种用法会导致问题:
<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
,但它没有任何改变。
我该如何解决这个问题?
控制台,
- 命名你的风格 :
<Style x:Key="MenuItemStyle1" TargetType="{x:Type MenuItem}">
- 并且每次您打算使用它时,请使用命名资源 :
<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
内,其中 Command
和 CommandProperty
位于内部 MenuItem
而样式位于外部 MenuItem
.这导致我的 Command
出现问题,因为外部 MenuItem
已经消耗了 Click
.
现在使用 ItemContainerStyle
setters 应用到正确的 MenuItem
而使用 BasedOn
属性 则采用全局 MenuItem
风格的所有 Setters .
我有一个 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
不会在任何地方使用原始 MenuItem
的 ItemTemplate
。
这种用法会导致问题:
<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
,但它没有任何改变。
我该如何解决这个问题?
控制台,
- 命名你的风格 :
<Style x:Key="MenuItemStyle1" TargetType="{x:Type MenuItem}">
- 并且每次您打算使用它时,请使用命名资源 :
<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
内,其中 Command
和 CommandProperty
位于内部 MenuItem
而样式位于外部 MenuItem
.这导致我的 Command
出现问题,因为外部 MenuItem
已经消耗了 Click
.
现在使用 ItemContainerStyle
setters 应用到正确的 MenuItem
而使用 BasedOn
属性 则采用全局 MenuItem
风格的所有 Setters .