У меня есть ContextMenu, связанный с HierarchicalDataTemplate, который отображает структуру TreeView. ContextMenu также является HierarchicalDataTemplate, который получает свою структуру через ObservableCollection моделей MenuItemViewModels.
Моя проблема в том, что при запуске программы щелчок правой кнопкой мыши по уже открытому ContextMenu нежелательно вызывает щелчок левой кнопкой мыши по элементу MenuItem - почему это так? Что мне не хватает? Я не могу найти ошибку в коде и буду признателен за любую помощь.
XAML для TreeView:
<HierarchicalDataTemplate x:Key = "TreeHierarchicalDataTemplate" DataType = "{x:Type model:TreeNodeBaseViewModel}" ItemsSource = "{Binding Path=SubItems, UpdateSourceTrigger=PropertyChanged}" ItemContainerStyle = "{StaticResource MenuItemTemplateItemContainerStyle}">
<!--...-->
</HierarchicalDataTemplate>
<Style x:Key = "MenuItemTemplateItemContainerStyle" TargetType = "{x:Type TreeViewItem}">
<Setter Property = "ContextMenu" Value = "{DynamicResource MenuItemContextMenu}"/>
<Setter Property = "IsEnabled" Value = "{Binding IsEnabled}"/>
<Setter Property = "AllowDrop" Value = "{Binding IsDropAllowed}"/>
<Setter Property = "IsExpanded" Value = "{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property = "IsSelected" Value = "{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property = "Tag" Value = "{Binding}"/>
<Style.Triggers>
<DataTrigger Binding = "{Binding Path=IsVisible}" Value = "False">
<Setter Property = "Visibility" Value = "Collapsed"/>
</DataTrigger>
<Trigger Property = "beh:TreeNodeMouseOver.IsMouseDirectlyOverItem" Value = "True">
<Setter Property = "Background" Value = "AliceBlue" />
</Trigger>
</Style.Triggers>
</Style>
XAML для ContextMenu:
<ContextMenu x:Key = "MenuItemContextMenu" ItemsSource = "{Binding RelativeSource = {RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=TreeViewModel.MenuItems, UpdateSourceTrigger=PropertyChanged}">
<ContextMenu.ItemTemplate>
<HierarchicalDataTemplate DataType = "{x:Type model:MenuItemBaseViewModel}" ItemsSource = "{Binding Path=SubItems, UpdateSourceTrigger=PropertyChanged}">
<TextBlock Text = "{Binding Header}"/>
</HierarchicalDataTemplate>
</ContextMenu.ItemTemplate>
<ContextMenu.ItemContainerStyle>
<Style TargetType = "MenuItem">
<Setter Property = "ToolTip" Value = "{Binding ToolTip}"/>
<Setter Property = "IsHitTestVisible" Value = "True"/>
<Setter Property = "IsEnabled" Value = "{Binding IsEnabled}"/>
<Setter Property = "Command" Value = "{Binding MouseLeftButtonDownCommand}"/> <!--LeftClick is bound to ViewModel here, but RightClick is not even defined anywhere in MenuItem or ViewModel-->
<Style.Triggers>
<DataTrigger Binding = "{Binding VisibleSubItems}" Value = "0">
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate TargetType = "{x:Type MenuItem}">
<Border x:Name = "templateRoot" BorderBrush = "{TemplateBinding BorderBrush}" BorderThickness = "{TemplateBinding BorderThickness}" Background = "{TemplateBinding Background}" SnapsToDevicePixels = "True">
<Grid Margin = "-1">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth = "22" SharedSizeGroup = "MenuItemIconColumnGroup" Width = "Auto"/>
<ColumnDefinition Width = "13"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "20"/>
<ColumnDefinition SharedSizeGroup = "MenuItemIGTColumnGroup" Width = "Auto"/>
<ColumnDefinition Width = "Auto"/>
<ColumnDefinition Width = "Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter x:Name = "Icon" Content = "{TemplateBinding Icon}" ContentSource = "Icon" HorizontalAlignment = "Center" Height = "16" Margin = "3" SnapsToDevicePixels = "{TemplateBinding SnapsToDevicePixels}" VerticalAlignment = "Center" Width = "16"/>
<Border x:Name = "GlyphPanel" BorderBrush = "#FF26A0DA" BorderThickness = "1" Background = "#3D26A0DA" ClipToBounds = "False" HorizontalAlignment = "Center" Height = "22" Margin = "-1,0,0,0" Visibility = "Hidden" VerticalAlignment = "Center" Width = "22">
<Path x:Name = "Glyph" Data = "F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill = "#FF212121" FlowDirection = "LeftToRight" Height = "11" Width = "10"/>
</Border>
<ContentPresenter x:Name = "menuHeaderContainer" ContentTemplate = "{TemplateBinding HeaderTemplate}" Content = "{TemplateBinding Header}" Grid.Column = "2" ContentStringFormat = "{TemplateBinding HeaderStringFormat}" ContentSource = "Header" HorizontalAlignment = "Left" Margin = "{TemplateBinding Padding}" RecognizesAccessKey = "True" SnapsToDevicePixels = "{TemplateBinding SnapsToDevicePixels}" VerticalAlignment = "Center"/>
<TextBlock x:Name = "menuGestureText" Grid.Column = "4" Margin = "{TemplateBinding Padding}" Opacity = "0.7" Text = "{TemplateBinding InputGestureText}" VerticalAlignment = "Center"/>
<Button Grid.Column = "5" Margin = "2" Command = "{Binding EditCommand}" Visibility = "{Binding IsEditVisible, Converter = {StaticResource BooleanToVisibilityConverter}}" Background = "Transparent" BorderThickness = "0">
<iconPacks:PackIconMaterialLight Width = "14" Height = "14" Foreground = "Black" HorizontalAlignment = "Center" VerticalAlignment = "Center" Kind = "Cog" />
</Button>
<Button Grid.Column = "6" Margin = "2" Command = "{Binding HelpCommand}" Visibility = "{Binding IsInfoVisible, Converter = {StaticResource BooleanToVisibilityConverter}}" Background = "Transparent" BorderThickness = "0">
<iconPacks:PackIconMaterial Width = "14" Height = "14" Foreground = "Blue" HorizontalAlignment = "Center" VerticalAlignment = "Center" Kind = "InformationOutline" />
</Button>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property = "Icon" Value = "{x:Null}">
<Setter Property = "Visibility" TargetName = "Icon" Value = "Collapsed"/>
</Trigger>
<Trigger Property = "IsChecked" Value = "True">
<Setter Property = "Visibility" TargetName = "GlyphPanel" Value = "Visible"/>
<Setter Property = "Visibility" TargetName = "Icon" Value = "Collapsed"/>
</Trigger>
<Trigger Property = "IsHighlighted" Value = "True">
<Setter Property = "Background" TargetName = "templateRoot" Value = "#3D26A0DA"/>
<Setter Property = "BorderBrush" TargetName = "templateRoot" Value = "#FF26A0DA"/>
</Trigger>
<Trigger Property = "IsEnabled" Value = "False">
<Setter Property = "TextElement.Foreground" TargetName = "templateRoot" Value = "#FF707070"/>
<Setter Property = "Fill" TargetName = "Glyph" Value = "#FF707070"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property = "IsHighlighted" Value = "True"/>
<Condition Property = "IsEnabled" Value = "False"/>
</MultiTrigger.Conditions>
<Setter Property = "Background" TargetName = "templateRoot" Value = "#0A000000"/>
<Setter Property = "BorderBrush" TargetName = "templateRoot" Value = "#21000000"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding = "{Binding IsVisible}" Value = "false">
<Setter Property = "MenuItem.Visibility" Value = "Collapsed"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconSimpleIconsKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource Simple}"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconEntypoKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource Entypo}"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconFontAwesomeKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource FontAwesome}"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconMaterialKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource Material}"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconMaterialLightKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource MaterialLight}"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconModernKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource Modern}"/>
</DataTrigger>
<DataTrigger Binding = "{Binding PackIcon.IconType}" Value = "{x:Type iconPacks:PackIconOcticonsKind}">
<Setter Property = "MenuItem.Icon" Value = "{StaticResource Octicons}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContextMenu.ItemContainerStyle>
<i:Interaction.Behaviors>
<beh:EventToCommandBehavior Command = "{Binding RelativeSource = {RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=TreeViewModel.ContextMenuOpenedCommand}" Event = "Opened" PassArguments = "True" />
</i:Interaction.Behaviors>
</ContextMenu>
Такое поведение предусмотрено дизайном. Если вам нужны отдельные обработчики щелчков левой и правой кнопкой мыши для пунктов меню, вам необходимо добавить соответствующие привязки MouseBindings в коллекцию MenuItem InputBindings. Если вам нужно сделать это в стиле, вы можете использовать поведение Attach в этом вопросе.
<ContextMenu.ItemContainerStyle>
<Style TargetType = "MenuItem">
<Setter Property = "behaviors:Attach.InputBindings">
<Setter.Value>
<InputBindingCollection>
<MouseBinding Gesture = "LeftClick" Command = "{Binding LeftClickCommand}" />
<MouseBinding Gesture = "RightClick" Command = "{Binding RightClickCommand}" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
</ContextMenu.ItemContainerStyle>
Большое спасибо, это сработало :-) Я использовал поведение Attach вашей ссылки, но мне также пришлось добавить x:Shared=false в InputBindingCollection и ссылаться на него как на StaticResource.