wpf context menu left-click

12,750

Solution 1

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.

Solution 2

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.

Share:
12,750
Tomasz Grobelny
Author by

Tomasz Grobelny

Updated on June 04, 2022

Comments

  • Tomasz Grobelny
    Tomasz Grobelny almost 2 years

    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).

  • Tomasz Grobelny
    Tomasz Grobelny almost 12 years
    Wouldn't doing it from code violate the separation between view and logic? To me this part belongs to view (and so should be specified in xaml).
  • Xcalibur37
    Xcalibur37 almost 12 years
    This is the code-behind of the view which is part of the view. What you are referring to would be in regard to implementing this code in a ViewModel and I am not suggesting that at all.
  • Tomasz Grobelny
    Tomasz Grobelny almost 12 years
    Ok, so be it. But still, I do not understand the "Create an event for LeftMouseButtonDown and call that method" part. I have a style for my control inside Generic.xaml. I want the context menu to show up when I click on one of the controls defined in this style eg. Image control. So I tried to add MouseUp="method" to the Image tag, but I get: error MC4007: The event 'MouseUp' cannot be specified on a Target tag in a Style. Use an EventSetter instead. How do I wire up the event handler from within a style? Where should my method be located? Generic.xaml.cs?
  • Xcalibur37
    Xcalibur37 almost 12 years
    I am putting a sample in a separate answer.
  • Tomasz Grobelny
    Tomasz Grobelny almost 12 years
    (Sorry for late reply.) But how do I move this behaviour to style (eg. in Generic.xml). As indicated in my previous comment I get "error MC4007: The event 'MouseUp' cannot be specified on a Target tag in a Style. Use an EventSetter instead."
  • Xcalibur37
    Xcalibur37 almost 12 years
    I agree with the error. You should use an Event setter. I don't believe there is an effective way to do that in a style since you need it to occur on a specific event.
  • The Cookies Dog
    The Cookies Dog almost 7 years
    Thanks, this is the only solution I've found that respects what you specify in the ContextMenuService.Placement... properties.