WPF ContextMenu с такими подменю, как флажки - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь реализовать контекстное меню с привязкой ViewModel, как показано ниже:

enter image description here

Стиль, кажется, в порядке, но я не могу найти способ реализовать подменю с флажками, привязанными к viewmodel.

, пожалуйста, найдите ниже код, который я использую для получения меню, подобного этому:

<Window x:Class="WpfContextMenu.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfContextMenu"
    xmlns:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">

<Window.Resources>
    <!-- Separator -->
    <Style TargetType="{x:Type Separator}"
       x:Key="SeparatorStyle">
        <Setter Property="Height"
            Value="0" />
        <Setter Property="Background"
            Value="#0f3c5a" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Separator}">
                    <Rectangle Height="{TemplateBinding Height}"
                           Fill="White" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--Outer menu items-->
    <Style TargetType="{x:Type MenuItem}">
        <Setter Property="Background" Value="Black"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="IsCheckable" Value="True"/>
        <Style.Triggers>
            <Trigger Property="IsHighlighted"
                 Value="True">
                <Setter Property="Background"
                    Value="Black"></Setter>
            </Trigger>
            <Trigger Property="IsEnabled"
                 Value="False">
                <Setter Property="Foreground"
                    Value="LightGray"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

    <!-- Outer menu -->
    <Style TargetType="{x:Type ContextMenu}">
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <Setter Property="SnapsToDevicePixels" Value="True" />            
        <Setter Property="Foreground" Value="LightGray"/>
        <Setter Property="Background" Value="Black"/>
        <Setter Property="Template">                
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ContextMenu}">
                    <!--Here is where you change the border thickness to zero on the menu-->
                    <Border BorderThickness="0"
                        x:Name="Border"
                        Background="Black">
                        <StackPanel ClipToBounds="True"
                                Orientation="Vertical"
                                IsItemsHost="True" Background="Black"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                             Value="true">
                            <Setter TargetName="Border"
                                Property="Background"
                                Value="#0f3c5a" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Submenu Item -->
    <ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}"
                 TargetType="{x:Type MenuItem}">            
        <Border Name="Border">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"
                                  SharedSizeGroup="Icon" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto"
                                  SharedSizeGroup="Shortcut" />
                    <ColumnDefinition Width="13" />
                </Grid.ColumnDefinitions>
                <ContentPresenter Name="Icon"
                              Margin="6,0,6,0"
                              VerticalAlignment="Center"
                              ContentSource="Icon" />
                <Border Name="Check"
                    Width="13"
                    Height="13"
                    Visibility="Collapsed"
                    Margin="6,0,6,0"
                    Background="Black"
                    BorderThickness="1"
                    BorderBrush="#5082a4">
                    <Path Name="CheckMark"
                      Width="7"
                      Height="7"
                      Visibility="Hidden"
                      SnapsToDevicePixels="False"
                      Stroke="#5082a4"
                      StrokeThickness="2"
                      Data="F1 M 0.468732,4.66838L 3.03345,7.95443L 7.28127,0.420569" />
                </Border>
                <ContentPresenter Name="HeaderHost"
                              Grid.Column="1"
                              ContentSource="Header"
                              RecognizesAccessKey="True" />
                <TextBlock x:Name="InputGestureText"
                       Grid.Column="2"
                       Text="{TemplateBinding InputGestureText}"
                       Margin="5,2,0,2"
                       DockPanel.Dock="Right" />
            </Grid>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="Icon"
                 Value="{x:Null}">
                <Setter TargetName="Icon"
                    Property="Visibility"
                    Value="Hidden" />
            </Trigger>
            <Trigger Property="IsChecked"
                 Value="true">
                <Setter TargetName="CheckMark"
                    Property="Visibility"
                    Value="Visible" />
            </Trigger>
            <Trigger Property="IsCheckable"
                 Value="true">
                <Setter TargetName="Check"
                    Property="Visibility"
                    Value="Visible" />
                <Setter TargetName="Icon"
                    Property="Visibility"
                    Value="Hidden" />
            </Trigger>
            <Trigger Property="IsHighlighted"
                 Value="true">
                <Setter TargetName="Border"
                    Property="Background"
                    Value="#5082a4" />
            </Trigger>
            <Trigger Property="IsEnabled"
                 Value="false">
                <Setter Property="Foreground"
                    Value="#0f3c5a" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <!-- Submenu Header -->
    <ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}"
                 TargetType="{x:Type MenuItem}">
        <Border Name="Border">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"
                                  SharedSizeGroup="Icon" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto"
                                  SharedSizeGroup="Shortcut" />
                    <ColumnDefinition Width="13" />
                </Grid.ColumnDefinitions>
                <ContentPresenter Name="Icon"
                              Margin="6,0,6,0"
                              VerticalAlignment="Center"
                              ContentSource="Icon" />
                <ContentPresenter Name="HeaderHost"
                              Grid.Column="1"
                              ContentSource="Header"
                              RecognizesAccessKey="True" />
                <TextBlock x:Name="InputGestureText"
                       Grid.Column="2"
                       Text="{TemplateBinding InputGestureText}"
                       Margin="5,2,2,2"
                       DockPanel.Dock="Right" />
                <Path Grid.Column="3"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"                          
                  Data="M 0 0 L 0 7 L 4 3.5 Z"
                  Fill="Red" Stretch="Fill" Height="15" Width="7"/>
                <Popup Name="Popup"
                   Placement="Right"
                   HorizontalOffset="-4"
                   IsOpen="{TemplateBinding IsSubmenuOpen}"
                   AllowsTransparency="True"
                   Focusable="False"
                   PopupAnimation="Fade">
                    <Border Name="SubmenuBorder"
                        SnapsToDevicePixels="True"
                        Background="Black"
                        BorderBrush="#0f3c5a"
                        BorderThickness="1">
                        <StackPanel IsItemsHost="True"
                                KeyboardNavigation.DirectionalNavigation="Cycle" />
                    </Border>
                </Popup>
            </Grid>
        </Border>

        <ControlTemplate.Triggers>
            <Trigger Property="Icon"
                 Value="{x:Null}">
                <Setter TargetName="Icon"
                    Property="Visibility"
                    Value="Collapsed" />
            </Trigger>
            <Trigger Property="IsHighlighted"
                 Value="true">
                <Setter TargetName="Border"
                    Property="Background"
                    Value="#5082a4" />
            </Trigger>
            <Trigger SourceName="Popup"
                 Property="Popup.AllowsTransparency"
                 Value="True">
                <Setter TargetName="SubmenuBorder"
                    Property="CornerRadius"
                    Value="4" />
                <Setter TargetName="SubmenuBorder"
                    Property="Padding"
                    Value="0,3,0,3" />
            </Trigger>
            <Trigger Property="IsEnabled"
                 Value="false">
                <Setter Property="Foreground"
                    Value="#0f3c5a" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

</Window.Resources>

<Grid>
    <Rectangle x:Name="rect1"
            Width="100"
            Height="30"
            Margin="5"               
            ContextMenuService.IsEnabled="False"
            ContextMenuService.Placement="Top"
            ContextMenuService.PlacementTarget="{Binding ElementName=rect1}"
            ContextMenuService.ShowOnDisabled="True"
            Fill="Gray"
            MouseDown="rect1_MouseDown">
        <Rectangle.ContextMenu>
            <ContextMenu ItemsSource="{Binding MenuItems}" FontSize="20">                   
                <ContextMenu.ItemTemplate>                        
                    <HierarchicalDataTemplate>
                        <ContentPresenter Content="{Binding MainMenuHeader}"/>
                        <HierarchicalDataTemplate.ItemsSource>
                            <Binding Path="SubItems"/>
                        </HierarchicalDataTemplate.ItemsSource>
                    </HierarchicalDataTemplate>                                                
                </ContextMenu.ItemTemplate>
            </ContextMenu>
        </Rectangle.ContextMenu>
    </Rectangle>
</Grid>

public class MainWindowViewModel : BindableBase
{
    private ObservableCollection<MenuItem> _menuItems = new ObservableCollection<MenuItem>();

    public MainWindowViewModel()
    {
        var menuItems = new MenuItem
        {
            MainMenuHeader = "Personal Customer Forms"
        };
        menuItems.SubItems.Add(new MenuItem { MainMenuHeader = "Sub 1"});
        menuItems.SubItems.Add(new MenuItem { MainMenuHeader = "Sub 2" });
        menuItems.SubItems.Add(new MenuItem { MainMenuHeader = "Sub 3" });
        MenuItems.Add(menuItems);

        var menuItems1 = new MenuItem
        {
            MainMenuHeader = "Second"
        };
        menuItems1.SubItems.Add(new MenuItem { MainMenuHeader = "Sub 1" });
        menuItems1.SubItems.Add(new MenuItem { MainMenuHeader = "Sub 2" });
        menuItems1.SubItems.Add(new MenuItem { MainMenuHeader = "Sub 3" });
        MenuItems.Add(menuItems1);
    }

    public ObservableCollection<MenuItem> MenuItems
    {
        get => _menuItems;
        set { _menuItems = value; RaisePropertyChanged(); }
    }
}

public class MenuItem : BindableBase
{
    private ObservableCollection<MenuItem> _subItems = new ObservableCollection<MenuItem>();

    public MenuItem()
    {

    }

    public string MainMenuHeader { get; set; }

    public ObservableCollection<MenuItem> SubItems 
    { 
        get => _subItems; 
        set 
        {
            _subItems = value;
            RaisePropertyChanged(); 
        } 
    }
}

Когда Я устанавливаю свойство IsCheckable для пункта меню в true, тогда только основные элементы становятся проверяемыми.

Буду признателен, если кто-то сможет помочь с этой проблемой.

Заранее спасибо.

...