我正在尝试从菜单项列表中填充菜单项,这样做我能够正确获取数据,但样式变得混乱,就好像我当前的样式和默认菜单有一个覆盖层项目风格
这是我的菜单中的示例项目列表
public IEnumerable MenuItems { 获取;放; } = new List() { "ItemA", "ItemB" };
这是主要代码
<Border Background="#fff">
<Menu>
<MenuItem Style="{StaticResource MenuItemDropDownBaseStyle}"
Header="Hello"
ItemsSource="{Binding MenuItems}">
<MenuItem.ItemTemplate>
<DataTemplate>
<!-- doesn't work -->
<MenuItem Header="{Binding }" Style="{StaticResource MenuItemBaseStyle}" />
</DataTemplate>
</MenuItem.ItemTemplate>
<!-- works -->
<!-- <MenuItem Header="ItemA" Style="{StaticResource MenuItemBaseStyle}" /> -->
<!-- <MenuItem Header="ItemB" Style="{StaticResource MenuItemBaseStyle}" /> -->
</MenuItem>
</Menu>
</Border>
这是我的 MenuItem 下拉列表和其中每个容器项目的样式
<Window.Resources>
<Color x:Key="White">#ffffff</Color>
<SolidColorBrush x:Key="BackgroundBrushWhite" Color="{StaticResource White}" />
<Color x:Key="Black">#000000</Color>
<SolidColorBrush x:Key="BackgroundBrushBlack" Color="{StaticResource Black}" />
<Color x:Key="Viking">#67cfdf</Color>
<SolidColorBrush x:Key="BackgroundBrushViking" Color="{StaticResource Viking}" />
<Color x:Key="MidnightBlue">#003966</Color>
<SolidColorBrush x:Key="BackgroundBrushMidnightBlue" Color="{StaticResource MidnightBlue}" />
<Color x:Key="CongressBlue">#014984</Color>
<SolidColorBrush x:Key="BackgroundBrushCongressBlue" Color="{StaticResource CongressBlue}" />
<Color x:Key="DullLavender">#8ca5e0</Color>
<SolidColorBrush x:Key="BackgroundBrushDullLavender" Color="{StaticResource DullLavender}" />
<Style x:Key="MenuItemDropDownBaseStyle" TargetType="MenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Grid>
<Border x:Name="ContentBorder" Padding="12, 7, 12, 7" CornerRadius="5" Margin="5">
<ContentPresenter ContentSource="Header"
TextBlock.Foreground="{StaticResource BackgroundBrushBlack}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
<Border CornerRadius="5"
Width="190"
Padding="0, 5, 0, 5"
Background="{StaticResource BackgroundBrushViking}">
<!--<ScrollViewer Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">-->
<Grid RenderOptions.ClearTypeHint="Enabled">
<!--<Canvas HorizontalAlignment="Center" VerticalAlignment="Center" />-->
<ItemsPresenter x:Name="ItemsPresenter" />
</Grid>
<!--</ScrollViewer>-->
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="ContentBorder" Value="{StaticResource BackgroundBrushViking}" />
<Setter Property="BorderBrush" TargetName="ContentBorder" Value="{StaticResource BackgroundBrushViking}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MenuItemBaseStyle" TargetType="MenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="ItemBorder" Height="32">
<Grid>
<ContentPresenter x:Name="ContentP"
ContentSource="Header"
TextBlock.Foreground="{StaticResource BackgroundBrushWhite}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
<Border x:Name="SideHighlight"
Height="{Binding RelativeSource={RelativeSource AncestorType=Border}, Path=Height}"
Width="4"
Background="{StaticResource BackgroundBrushCongressBlue}"
CornerRadius="0, 50, 50, 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Visibility="Collapsed" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="TextBlock.Foreground" TargetName="ContentP" Value="{StaticResource BackgroundBrushMidnightBlue}" />
<Setter Property="Visibility" TargetName="SideHighlight" Value="Visible" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="ItemBorder" Value="blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
我尝试在 ItemContainerStyle 中应用我的自定义样式,但无论如何都不起作用,我知道我在这里错过了一些东西,但无法弄清楚
MenuItem
是一个ItemsControl
(一个HeaderdItemsControl
)。因此,它会自动生成一个项目容器来托管项目的内容。这个容器本身就是 MenuItem
类型。 MenuItem
是一个可以承载子容器的容器。
您的正确行为示例省略了自动项目容器创建,因为您显式添加了这些容器:
<MenuItem>
<MenuItem /> <!-- Explicit child container -->
</MenuItem>
“非工作”示例定义了
DataTemplate
,并且通过将项目绑定到 MenuItem.ItemsSource
隐式添加子元素:父元素 MenuItem
将生成类型为 MenuItem
的项目容器,并将数据项设置为它的内容。然后内容的视觉效果由 DataTemplate
定义,在您的情况下定义另一个 MenuItem
。
结果是一个
MenuItem
(项目容器),其内容为 MenuItem
(来自 DataTemplate
)。这会导致不期望的布局。Style
,而在于DataTemplate
。
要解决此问题,请从
MenuItem
中删除 DataTemplate
。相反,提供一个托管数据项表示的元素,例如 TextBlock
:
<DataTemplate>
<TextBlock text="{Binding} />
</DataTemplate>
虽然这可以让它工作,但
DataTemplate
本身几乎是多余的。它仅显示 string
值(源集合是 string
项的集合)。HeaderedItemsControl
默认会自动创建类似的内容模板。MenuItem
的子项目:
<!-- Will automatically show "Item A" and "Item B" as child menu items -->
<MenuItem Style="{StaticResource MenuItemDropDownBaseStyle}"
Header="Hello"
ItemsSource="{Binding MenuItems}" />
如果内容布局复杂,您只需定义一个
DataTemplate
。
要显式指定 chld 项的
Style
,只需设置 ItemsControl.ItemContainer
属性:
<!-- Will automatically show "Item A" and "Item B" as child menu items -->
<MenuItem Style="{StaticResource MenuItemDropDownBaseStyle}"
Header="Hello"
ItemsSource="{Binding MenuItems}"
ItemContainerStyle="{StaticResource MenuItemBaseStyle}" />
如果数据项比较复杂,您可以通过设置
ItemsControl.DispalyMemberPath
: 来控制应显示为标题的属性
<!-- Will automatically show "Item A" and "Item B" as child menu items -->
<MenuItem Style="{StaticResource MenuItemDropDownBaseStyle}"
Header="Hello"
ItemsSource="{Binding MenuItems}"
ItemContainerStyle="{StaticResource MenuItemBaseStyle}"
DispalyMemberPath="NameOfSomePropertyOnTheItemThatShouldBeTheHeader" />