将样式应用于从可观察集合填充的菜单项

问题描述 投票:0回答:1

我正在尝试从菜单项列表中填充菜单项,这样做我能够正确获取数据,但样式变得混乱,就好像我当前的样式和默认菜单有一个覆盖层项目风格

请看一下图片 Working Not Working

这是我的菜单中的示例项目列表

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 中应用我的自定义样式,但无论如何都不起作用,我知道我在这里错过了一些东西,但无法弄清楚

c# wpf xaml
1个回答
0
投票

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" /> 
© www.soinside.com 2019 - 2024. All rights reserved.