菜单上的绑定项目集合将显示在MenuItem弹出窗口上

时间:2018-10-15 20:00:57

标签: c# wpf xaml

我需要具有一个带有动态子项的MenuItem(实际上是一个汉堡包按钮)的自定义Menu(继承菜单的AMTMenu类以及一些其他DependencyProperties),因为此菜单将在许多布局中重复使用。除此之外,它还应该显示其他5个TopLevel菜单项,这些菜单项显示了包含在DataContext上的信息,没有附加任何子项和一个刷新按钮。除我单击汉堡菜单项时未显示子菜单部分外,其他菜单项均正常运行,因为我似乎无法正确绑定项目。这是我到目前为止的代码:

<Menu.Template>
    <ControlTemplate>
        <Grid Name="ContentGrid"
              Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
              IsItemsHost="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="HamburgerButtonColumn" Width="5*" />
                <ColumnDefinition x:Name="ButtonsColumn" Width="90*" />
                <ColumnDefinition x:Name="RefreshButtonColumn" Width="5*"/>
            </Grid.ColumnDefinitions>
            <MenuItem Foreground="{DynamicResource BlackBrush}"
                      Focusable="False"
                      Template="{DynamicResource MainMenuButtonTemplate}">
                <MenuItem.Icon>
                    <iconPacks:PackIconMaterial Kind="Menu"
                                                HorizontalAlignment="Left"
                                                VerticalAlignment="Center"
                                                MinHeight="20" />
                </MenuItem.Icon>
            </MenuItem>
            <UniformGrid Name="ButtonsUniformGrid"
                         Grid.Column="1"
                         Columns="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AMTMenu}}, Path=ButtonCount}"
                         Rows="1"
                         HorizontalAlignment="Stretch">
                <MenuItem Grid.Column="0"
                          Template="{DynamicResource OiButtonsTemplate}"
                          Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource OiMainMenuButtonsColorBrushConverter}}"
                          Focusable="False"
                          Command="{Binding ShowRefreshDataCommand}"
                          CommandParameter="Button1">
                    <MenuItem.Tag>
                        <MultiBinding Converter="{StaticResource MainMenuButtonsTextConverter}" ConverterParameter="INC">
                            [ ... MultiBinding logic ... ]
                        </MultiBinding>
                    </MenuItem.Tag>
                </MenuItem>

                [ ... XAML Code for the other 4 MenuItems ... ]

            </UniformGrid>
            <DockPanel Name="PART_Refresh"
                       Grid.Column="2"
                       HorizontalAlignment="Stretch"
                       VerticalAlignment="Stretch">

                [ ... XAML Code for the refresh button ... ]

            </DockPanel>
        </Grid>
    </ControlTemplate>
</Menu.Template>

关于汉堡菜单项,我有以下模板:

<ControlTemplate x:Key="MainMenuButtonTemplate"
                 TargetType="{x:Type MenuItem}">
    <Grid SnapsToDevicePixels="true"
          HorizontalAlignment="Stretch">
        <StackPanel Background="{TemplateBinding Background}"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center">
            <ContentControl x:Name="PART_Button"
                            Foreground="{TemplateBinding Foreground}"
                            Background="{TemplateBinding Background}"
                            Content="{TemplateBinding Icon}"
                            Focusable="False" />
        </StackPanel>
        <Popup x:Name="PART_Popup" 
               AllowsTransparency="true"
               Focusable="false"
               HorizontalOffset="1"
               IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
               PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
               Placement="Bottom"
               VerticalOffset="-1">
            <Border BorderThickness="2"
                    BorderBrush="White"
                    Background="{TemplateBinding Background}">
                <ScrollViewer x:Name="SubMenuScrollViewer"
                              CanContentScroll="true"
                              Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
                    <Grid RenderOptions.ClearTypeHint="Enabled">
                        <ItemsPresenter x:Name="ItemsPresenter"
                                        KeyboardNavigation.DirectionalNavigation="Cycle"
                                        Grid.IsSharedSizeScope="true"
                                        Margin="2"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                        KeyboardNavigation.TabNavigation="Cycle"/>
                    </Grid>
                </ScrollViewer>
            </Border>
        </Popup>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Foreground" Value="{DynamicResource AccentColorBrush}" TargetName="PART_Button"/>
            <Setter Property="Background" Value="{DynamicResource GrayBrush}" TargetName="PART_Button"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

最后,我使用以下XAML声明菜单和子菜单:

<local:AMTMenu x:Name="MainMenu"
                   DockPanel.Dock="Top"
                   DataContext="{Binding CurrentModel}"
                   IsButton1Visible="True"
                   IsButton2Visible="True"
                   IsButton3Visible="True"
                   IsButton4Visible="True"
                   IsButton5Visible="False">
    <MenuItem Header="Item 1" />
    <Separator />
    <MenuItem Header="Item 2" />
    <Separator />
    <MenuItem Header="Item 3" />
</local:AMTMenu>

如何绑定菜单上的Items集合以显示在汉堡MenuItem弹出窗口上?

1 个答案:

答案 0 :(得分:0)

所以我发现了问题,在此发布以帮助有类似问题的任何人...问题是在模板上声明了汉堡菜单项,因此,菜单没有任何子项,因此未触发IsSubmenuOpen MenuItem上的属性。在意识到这一点之后,解决方案非常简单,用ItemsPresenter替换了模板上的MenuItem并将MenuItem移至Menu内容。另外,由于Menu现在在其类中定义了Items,所以我无法像以前一样声明子菜单,它将仅替换默认项,因此必须使用一个名为SubMenuItems的新DependencyProperty。

这是最终代码:

AMTMenu.xaml

<Menu>
    <Menu.Template>
        <ControlTemplate>
            <Grid Name="ContentGrid"
                  Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
                  IsItemsHost="True">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition x:Name="HamburgerButtonColumn" Width="5*" />
                    <ColumnDefinition x:Name="ButtonsColumn" Width="90*" />
                    <ColumnDefinition x:Name="RefreshButtonColumn" Width="5*"/>
                </Grid.ColumnDefinitions>
                <ItemsPresenter x:Name="ItemsPresenter"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                KeyboardNavigation.DirectionalNavigation="Cycle"
                                Grid.IsSharedSizeScope="true"
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                KeyboardNavigation.TabNavigation="Cycle" />
                <UniformGrid Name="ButtonsUniformGrid"
                             Grid.Column="1"
                             Columns="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AMTMenu}}, Path=ButtonCount}"
                             Rows="1"
                             HorizontalAlignment="Stretch">
                    <MenuItem Grid.Column="0"
                              Template="{DynamicResource OiButtonsTemplate}"
                              Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource OiMainMenuButtonsColorBrushConverter}}"
                              Focusable="False"
                              Command="{Binding ShowRefreshDataCommand}"
                              CommandParameter="Button1">
                        <MenuItem.Tag>
                            <MultiBinding Converter="{StaticResource MainMenuButtonsTextConverter}" ConverterParameter="INC">
                                [ ... MultiBinding logic ... ]
                            </MultiBinding>
                        </MenuItem.Tag>
                    </MenuItem>

                    [ ... XAML Code for the other 4 MenuItems ... ]

                </UniformGrid>
                <DockPanel Name="PART_Refresh"
                           Grid.Column="2"
                           HorizontalAlignment="Stretch"
                           VerticalAlignment="Stretch">

                    [ ... XAML Code for the refresh button ... ]

                </DockPanel>
            </Grid>
        </ControlTemplate>
    </Menu.Template>
    <MenuItem Foreground="{DynamicResource BlackBrush}"
              Focusable="False"
              Template="{DynamicResource MainMenuButtonTemplate}"
              AllowDrop="True"
              ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:AMTMenu}, Path=SubMenuItems}">
        <MenuItem.Icon>
            <iconPacks:PackIconMaterial Kind="Menu" MinHeight="20" />
        </MenuItem.Icon>
    </MenuItem>
</Menu>

父视图上的菜单声明:

<local:AMTMenu x:Name="MainMenu"
               DockPanel.Dock="Top"
               DataContext="{Binding CurrentModel}"
               IsButton1Visible="True"
               IsButton2Visible="True"
               IsButton3Visible="True"
               IsButton4Visible="True"
               IsButton5Visible="False">
    <local:AMTMenu.SubMenuItems>
        <local:SubMenuItemsCollection>
            <MenuItem Header="Item 1" />
            <Separator />
            <MenuItem Header="Item 2" />
            <Separator />
            <MenuItem Header="Item 3" />
        </local:SubMenuItemsCollection>
    </local:AMTMenu.SubMenuItems>
</local:AMTMenu>

其中SubMenuItemsCollection只是从ObservableCollection派生的类

public class SubMenuItemsCollection : ObservableCollection<FrameworkElement> { }

希望这对以后的人有所帮助;)