Is it possible to attach context menu to a wpf control and have it opened on left-click (as opposed to more customary right-click)? I want to achieve that using xaml only (this should be a part of my control's view template).
4 Answers
Here is a way to show context menu on left-click:
Create a new left button handler on the Border element:
<Border x:Name="Win"
Width="40"
Height="40"
Background="Purple"
MouseLeftButtonUp="UIElement_OnMouseLeftButtonUp">
and then add this:
private void UIElement_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
var mouseDownEvent =
new MouseButtonEventArgs(Mouse.PrimaryDevice,
Environment.TickCount,
MouseButton.Right)
{
RoutedEvent = Mouse.MouseUpEvent,
Source = Win,
};
InputManager.Current.ProcessInput(mouseDownEvent);
}
What it does, it basically maps the left-click into right-click. For reusability, you can wrap this into an attached behavior.
1 Comment
Here is how I would do a simple example of what I am suggesting:
The XAML:
<Window x:Class="LeftClickMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Grid>
<Border Width="400" Height="300" Background="#ccc" BorderBrush="#333"
BorderThickness="1"
MouseLeftButtonDown="Border_MouseLeftButtonDown"
MouseRightButtonUp="Border_MouseRightButtonUp">
<Border.ContextMenu>
<ContextMenu x:Name="myContextMenu">
<MenuItem Header="Menu Item 1" />
<MenuItem Header="Menu Item 2" />
<MenuItem Header="Menu Item 3" />
<MenuItem Header="Menu Item 4" />
<MenuItem Header="Menu Item 5" />
</ContextMenu>
</Border.ContextMenu>
</Border>
</Grid>
</Window>
And the code-behind:
using System.Windows;
using System.Windows.Input;
namespace LeftClickMenu
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
myContextMenu.IsOpen = true;
}
private void Border_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
}
}
I also added the extra MouseRightButtonUp event to inhibit the right-click popup of the context menu.
2 Comments
Create a method to programmatically open a submenu as stated in this SO article: Show menu programmatically in WPF
Create an event for LeftMouseButtonDown and call that event in XAML.
4 Comments
In order to open a ContextMenu in WPF with a left click, you need to ensure that the DataContext is properly bound. Here is a simple solution using a button:
<Button x:Name="myButton"
Content="Left Click Me"
MouseRightButtonUp="_myButton_MouseRightButtonUp"
PreviewMouseLeftButtonDown="_myButton_MouseLeftButtonDown">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Item 1"/>
<Separator/>
<MenuItem Header="Item 2"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
In the code behind, you need to ensure that the right click event is canceled first, then properly bind the DataContext to left click event.
/// <summary>
/// Cancels the default right-click event on a button to prevent displaying the ContextMenu
/// </summary>
private void _myButton_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
/// <summary>
/// Displays the ContextMenu of the button when the user left-clicks the mouse button
/// </summary>
private void _myButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var button = sender as Button;
if (button != null)
{
button.ContextMenu.DataContext = button.DataContext;
button.ContextMenu.IsOpen = true;
}
}