Этот ответ выполняет ту же работу, что и ответ @nightcoder (спасибо за вдохновение!). Он использует Blend-стиль поведения, который является более современным подходом по сравнению с присоединенным свойством.
using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Interactivity;
/// <summary>
/// Add this to any button menu allow a left click to open the context menu as well as the right.
/// </summary>
public class ContextMenuLeftClickBehavior : Behavior<ButtonBase>
{
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.Loaded += this.OnWindowLoaded;
this.AssociatedObject.Unloaded += this.OnWindowUnloaded;
}
private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
this.AssociatedObject.Click += OnMouseLeftButtonUp;
}
private void OnWindowUnloaded(object sender, RoutedEventArgs e)
{
this.AssociatedObject.Click -= OnMouseLeftButtonUp; // Cannot override OnDetached(), as this is not called on Dispose. Known issue in WPF.
}
private static void OnMouseLeftButtonUp(object sender, RoutedEventArgs e)
{
if (sender is ButtonBase fe && fe.ContextMenu != null)
{
if (fe.ContextMenu != null)
{
// If we use binding in our context menu, then it's DataContext won't be set when we show the menu on left click. It
// seems setting DataContext for ContextMenu is hardcoded in WPF when user right clicks on a control? So we have to set
// up ContextMenu.DataContext manually here.
if (fe.ContextMenu?.DataContext == null)
{
fe.ContextMenu?.SetBinding(FrameworkElement.DataContextProperty, new Binding { Source = fe.DataContext });
}
fe.ContextMenu.IsOpen = true;
}
}
}
}
Затем добавьте поведение к кнопке:
<Button>
<i:Interaction.Behaviors>
<attachedProperties:ContextMenuLeftClickBehavior/>
</i:Interaction.Behaviors>
<Button>
Такие элементы, как Ellipse или Rectangle, не имеют события OnClick
, что означает, что на самом деле ничего не работает очень хорошо для чего-либо интерактивного. Так что заверните все в кнопку, чтобы получить это OnClick
событие. Можно также намекнуть, что область доступна для нажатия, если навести курсор мыши на курсор мыши.
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Ellipse Fill="{TemplateBinding Background}" Width="16" Height="16"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- Bind to custom color in ViewModel -->
<Setter Property="Background" Value="{Binding CustomBrush}"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>