I'm trying to create a ContextMenu on a UserControl derived object. Note: This is NOT a WinForms App, it is pure WPF.
So I create the ContextMenu thus:
<UserControl.Resources>
<ContextMenu x:Key="cmLCD_CopyCutPaste">
<MenuItem Name="CutOption" Header="{x:Static p:Resources.Popup_Cut}" Command="Cut" Click="MenuItem_Cut" IsEnabled="True"/>
<MenuItem Name="CopyOption" Header="{x:Static p:Resources.Popup_Copy}" Command="Copy" Click="MenuItem_Copy" IsEnabled="True"/>
<MenuItem Name="PasteOption" Header="{x:Static p:Resources.Popup_Paste}" Command="Paste" Click="MenuItem_Paste" IsEnabled="True"/>
</ContextMenu>
</UserControl.Resources>
The mousebutton event is setup thus:
d:DesignHeight="66" d:DesignWidth="340" Focusable="True" KeyDown="Grid_KeyDown" MouseRightButtonDown="EMS_UI_LCDscreen_MouseRightButtonDown" >
In the code behind, the constructor starts like this:
public EMS_UI_LCDscreen()
{
InitializeComponent();
// Find the ContextMenu created on this object - it is called cmLCD_CopyCutPaste
ContextMenu cm = FindResource("cmLCD_CopyCutPaste") as ContextMenu;
// If we found the contextMenu, assign it the ContextMenu placeholder for this instance.
if (cm != null)
{
ContextMenu = cm;
}
...
The mouse click(right button) is handled like this:
private void EMS_UI_LCDscreen_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if (this.ContextMenu is ContextMenu cm)
{
if (cm != null)
{
if (DataContext is DeviceEditorData ded)
{
cm.DataContext = ded.Device.GetStructuredLocation(0);
cm.IsEnabled = true;
cm.PlacementTarget = sender as Button;
cm.IsOpen = true;
}
}
}
}
There are the three event handlers to actually respond to the user selection on the ContextMenu:
private void MenuItem_Cut(object sender, RoutedEventArgs e)
{
}
private void MenuItem_Copy(object sender, RoutedEventArgs e)
{
}
private void MenuItem_Paste(object sender, RoutedEventArgs e)
{
}
View of the ContextMenu being shown on the LCD Image component
The component I have created appears in a few different contexts, but the one I'm mainly interested in is inside of a DataGrid that shows various items of data, each with one of these components. when right clicked, the component faithfully displays the popup context menu as expected..... BUT all the items on the menu are grayed out and basically not enabled.
So my question is, what is the missing piece of glue that effectively enables the menu items so that they can be clicked to do the required actions. Most of the answers already seen on the net go into detail of how to do it in a WinForms app, but despite hours of searching, I can find no clear solution to what should be a very simple task of enabling the menu items.
Can some kind soul please put me out of my anguish and in a few lines of code show me how to do it! Thank you
UPDATE: This is the XAML implementation for the LCD Component:
<UserControl x:Class="EMS_Config_Tool.UIComponents.WPF.EMS_UI_LCDscreen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p="clr-namespace:EMS_Config_Tool.Properties"
mc:Ignorable="d"
d:DesignHeight="66" d:DesignWidth="340" Focusable="True" KeyDown="Grid_KeyDown" MouseRightButtonDown="EMS_UI_LCDscreen_MouseRightButtonDown" >
<UserControl.Resources>
<ContextMenu x:Key="cmLCD_CopyCutPaste">
<MenuItem Name="CutOption" Header="{x:Static p:Resources.Popup_Cut}" Command="{Binding Cut}"/>
<MenuItem Name="CopyOption" Header="{x:Static p:Resources.Popup_Copy}" Command="{Binding Copy}"/>
<MenuItem Name="PasteOption" Header="{x:Static p:Resources.Popup_Paste}" Command="{Binding Paste}"/>
</ContextMenu>
</UserControl.Resources>
<UserControl.CommandBindings>
<CommandBinding Command="Cut"
CanExecute="CutCommand_CanExecute"
Executed="CutCommand_Executed" />
<CommandBinding Command="Copy"
CanExecute="CopyCommand_CanExecute"
Executed="CopyCommand_Executed" />
<CommandBinding Command="Paste"
CanExecute="PasteCommand_CanExecute"
Executed="PasteCommand_Executed" />
</UserControl.CommandBindings>
</UserControl>
As can be seen, it is very simple - there are no items added to the control - it only serves as a Canvas upon which the code behind draws all the needed items which are purely graphic "draw" items.
This is the implementations of the 6 methods referenced, in the corresponding .cs file for the xaml above:
private void CutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// Verify relevant conditions and set CanExecuteRoutedEventArgs.CanExecute accordingly
e.CanExecute = true;
}
private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Execute the command action
if (sender is EMS_UI_LCDscreen lcd)
{
if (TheDevice != null)
{
Clipboard.SetDataObject(TheDevice.GetStructuredLocation(0).ToString());
TheDevice.SetLocation(0, "");
lcd.StructuredTextToShow = TheDevice.GetStructuredLocation(0);
}
else
{
Clipboard.SetDataObject(lcd.StructuredTextToShow.ToString());
lcd.StructuredTextToShow.SetString("");
}
}
}
private void CopyCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// Verify relevant conditions and set CanExecuteRoutedEventArgs.CanExecute accordingly
e.CanExecute = true;
}
private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Execute the command action
if (sender is EMS_UI_LCDscreen lcd)
{
if (TheDevice!=null)
Clipboard.SetDataObject(TheDevice.GetStructuredLocation(0).ToString());
else
Clipboard.SetDataObject(lcd.StructuredTextToShow.ToString());
}
}
private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// Verify relevant conditions and set CanExecuteRoutedEventArgs.CanExecute accordingly
IDataObject iData = Clipboard.GetDataObject();
// Is the Data Text?
if (iData.GetDataPresent(DataFormats.Text))
e.CanExecute = true;
else
e.CanExecute = false;
}
private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Execute the command action
if (sender is EMS_UI_LCDscreen lcd)
{
// Retrieves data
IDataObject iData = Clipboard.GetDataObject();
// Is the Data Text?
if (iData.GetDataPresent(DataFormats.Text))
{
if (TheDevice != null)
{
TheDevice.SetLocation(0, (string)iData.GetData(DataFormats.Text));
lcd.StructuredTextToShow = TheDevice.GetStructuredLocation(0);
}
else
{
lcd.StructuredTextToShow.SetString((string)iData.GetData(DataFormats.Text));
}
}
}
}
Finally, the ContextMenu is assigned to the object in the constructor:
public EMS_UI_LCDscreen()
{
InitializeComponent();
// Find the ContextMenu created on this object - it is called cmLCD_CopyCutPaste
ContextMenu cm = FindResource("cmLCD_CopyCutPaste") as ContextMenu;
// If we found the contextMenu, assign it the ContextMenu placeholder for this instance.
if (cm != null)
{
ContextMenu = cm;
}
...
The menu is shown on the component in response to right-click, the cut/copy/paste methods respond to the key ops, but clicking on the menu items does not fire the corresponding methods.
I can't see why that should be so, it all looks correct to me, but perhaps there is something missing that is preventing it working. One suggestion was to use a "relay command" type of thingy, but what and how that may be, is unclear.
You should remove all code that sets IsEnabled to true. It's redundant as the value is true by default.
The buttons are disabled because you have (accidentally?) attached a command to the MenuItem.Command property but no corresponding command handler.
The framework will try to invoke a CanExecute handler. Since there is no one defined, a default handler is returned that sets CanExecuteRoutedEventArgs.CanExecute to false, which will disable the button (ICommandSource).
Not sure if your intention was to use a command here or you wrongfully guessed the Command property is like a name property (since you have also registered Click event handlers). See Commanding Overview to learn more.
Anyway, this is how you can register a command handler:
You have assigned predefined application commands (cut, copy and paste - the MenuItem.Command string values in your XAML implicitly references the static ApplicationCommands commands). These commands are routed commands (behavior is identical to routed events - in fact routed commands are routed events). Therefore, you must define the command bindings on a parent element of the command source (the element that invokes the command) as the command will bubble up the tree.
A UIElement.CommandBinding consists of the specified CommandBinding.Executed handler and the optional CommandBinding.CanExecute handler.
Use the CanExecute handler to control the disabled states of the command source e.g., a Button. If the command source should be always enabled, simply omit the CanExecute handler.
XAML
<Window>
<Window.CommandBindings>
<CommandBinding Command="Cut"
CanExecute="CutCommand_CanExecute"
Executed="CutCommand_Executed" />
</Window.CommandBindings>
</Window>
C#
partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var cutCommandBinding =
new CommandBinding(ApplicationCommands.Cut, CutCommand_Executed, CutCommand_CanExecute)
this.CommandBindings.Add(cutCommandBinding);
}
}
Then create the corresponding command handlers in the code-behind.
private void CutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// Verify relevant conditions and set CanExecuteRoutedEventArgs.CanExecute accordingly
e.CanExecute = true;
}
private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Execute the command action
}
Update
To force command handling on the UserControl, you can explicitly set the MenuItem.CommandTarget property to reference the UserControl.
You can also assign the UserControl.Contextmenu from XAML:
<UserControl>
<UserControl.Resources>
<Style TargetType="MenuItem">
<Setter Property="CommandTarget"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=PlacementTarget}" />
</Style>
</UserControl.Resources>
<UserControl.Contextmenu>
<ContextMenu>
<MenuItem Name="CutOption" Header="{x:Static p:Resources.Popup_Cut}" Command="{Binding Cut}"/>
<MenuItem Name="CopyOption" Header="{x:Static p:Resources.Popup_Copy}" Command="{Binding Copy}"/>
<MenuItem Name="PasteOption" Header="{x:Static p:Resources.Popup_Paste}" Command="{Binding Paste}"/>
</ContextMenu>
</UserControl.Contextmenu>
<UserControl.CommandBindings>
<CommandBinding Command="Cut"
CanExecute="CutCommand_CanExecute"
Executed="CutCommand_Executed" />
<CommandBinding Command="Copy"
CanExecute="CopyCommand_CanExecute"
Executed="CopyCommand_Executed" />
<CommandBinding Command="Paste"
CanExecute="PasteCommand_CanExecute"
Executed="PasteCommand_Executed" />
</UserControl.CommandBindings>
</UserControl>
This was the solution that finally worked for me. The elixir was assigning the commands, not with the "Binding" term, but directly:
<UserControl x:Class="EMS_Config_Tool.UIComponents.WPF.EMS_UI_LCDscreen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p="clr-namespace:EMS_Config_Tool.Properties"
mc:Ignorable="d"
d:DesignHeight="66" d:DesignWidth="340" Focusable="True" KeyDown="Grid_KeyDown" MouseRightButtonDown="EMS_UI_LCDscreen_MouseRightButtonDown" >
<UserControl.Resources>
<Style TargetType="MenuItem">
<Setter Property="CommandTarget"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=PlacementTarget}" />
</Style>
</UserControl.Resources>
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Name="CutOption" Header="{x:Static p:Resources.Popup_Cut}" Command="Cut" />
<MenuItem Name="CopyOption" Header="{x:Static p:Resources.Popup_Copy}" Command="Copy" />
<MenuItem Name="PasteOption" Header="{x:Static p:Resources.Popup_Paste}" Command="Paste" />
</ContextMenu>
</UserControl.ContextMenu>
<UserControl.CommandBindings>
<CommandBinding Command="Cut"
CanExecute="CutCommand_CanExecute"
Executed="CutCommand_Executed" />
<CommandBinding Command="Copy"
CanExecute="CopyCommand_CanExecute"
Executed="CopyCommand_Executed" />
<CommandBinding Command="Paste"
CanExecute="PasteCommand_CanExecute"
Executed="PasteCommand_Executed" />
</UserControl.CommandBindings>
</UserControl>
The constructor and assignment of images looks like this:
public EMS_UI_LCDscreen()
{
InitializeComponent();
Image ObjImage1 = new Image();
Image ObjImage2 = new Image();
Image ObjImage3 = new Image();
ObjImage1.Source = new BitmapImage(new Uri(#"pack://application:,,,/Graphics\Misc Icons\Cut.png"));
CutOption.Icon = ObjImage1;
ObjImage2.Source = new BitmapImage(new Uri(#"pack://application:,,,/Graphics\Misc Icons\Copy.png"));
CopyOption.Icon = ObjImage2;
ObjImage3.Source = new BitmapImage(new Uri(#"pack://application:,,,/Graphics\Misc Icons\Paste.png"));
PasteOption.Icon = ObjImage3;
...
... and displaying the context menu on the component in response to the mouse right click:
private void EMS_UI_LCDscreen_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if (ContextMenu is ContextMenu cm)
{
if (DataContext is DeviceEditorData ded)
{
cm.DataContext = ded.Device.GetStructuredLocation((uint)LocationIndex);
cm.IsEnabled = true;
cm.PlacementTarget = sender as EMS_UI_LCDscreen;
cm.IsOpen = true;
}
if (DataContext is EMSBasicDevice dev)
{
cm.DataContext = dev.GetStructuredLocation((uint)LocationIndex);
cm.IsEnabled = true;
cm.PlacementTarget = sender as EMS_UI_LCDscreen;
cm.IsOpen = true;
}
}
}
For brevity, I have not shown the ..._CanExecute / ...Executed methods, they are as shown previously in the question.
Thanks to all who have helped in resolving this issue.
View of the finished context Menu in situ
So, if you are using DataContext and Binding's, you can do the following
remove the direct control with event handlers, i.e. Click, and direct setting of Enabled.
use Binding to bind menu action to the handler inside the view model: Command={Binding CutCommand} (or any other handler).
use ICommand.CanExecute of the command handler (CutCommand in the sample above). to manage Enabled state of menu item.
So, let's put all together.
In the XAML
<MenuItem Name="CutOption" Header="{x:Static p:Resources.Popup_Cut}"
Command="{Binding CutCommand}"/>
In the ViewModel
class ViewModel: INotifyPropertyChanged
{
...
public ICommand CutCommand { get; }
public ViewModel()
{
//you can just omit second arg if you always can call Cut.
CutCommand = new RelayCommand(CutHandler, ()=>CanCut()));
}
...
}
Here RelayCommand is a https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/relaycommand or any other implementation of simple command.
If you need to update the Enabled state on-the-fly, you can call CommandManager.InvalidateRequerySuggested(); to reevaluate CanExecute of all commands.
I am trying to use an ItemTemplate to create a list of menu items based on an enum. The problem is that, when I use the item template, the sub-menu appears in the top left corner of the screen (see Image 1) instead of next to the sub-menu header like the one with items defined within XAML (see image 2).
Items generated from enum:
Items defined in the XAML:
I would like to have the items sourced from the resource but still appear inside the menu flow like it does in the second example.
Here is the relevant code:
<Menu>
<MenuItem Header="🝖 Advanced Filters">
<MenuItem Header="Status"
ItemsSource="{Binding Source={StaticResource Statuses}}">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Converter={StaticResource EnumCaseConverter}}" />
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
<MenuItem Header="Submenu 2">
<MenuItem Header="Item 1" />
<MenuItem Header="Item 2" />
</MenuItem>
</MenuItem>
</Menu>
If it is relevant, my project includes Material Design.
Material design menus example
My solution was to do it programmatically instead of in XAML.
If anyone has a simple fix that is entirely in XAML, I'd be happy to see what the solution is.
private void PopulateFilterMenu()
{
// Create sub-menus
MenuItem status = AddMenuItem(FilterMenu, "Status", false);
MenuItem type = AddMenuItem(FilterMenu, "Type", false);
// Add status items
foreach (string item in Enum.GetNames(typeof(Statuses)))
AddMenuItem(status, item, true);
// Add type items
foreach (string item in Enum.GetNames(typeof(Type)))
AddMenuItem(type, item, true);
}
private MenuItem AddMenuItem(MenuItem parent, string header, bool checkable = false)
{
if (parent == null) { return parent; }
MenuItem menuItem = new MenuItem
{
Header = EnumCaseConverter.Convert(header),
IsCheckable = checkable,
IsChecked = checkable
};
parent.Items.Add(menuItem);
return menuItem;
}
hello I am pretty new to wpf c#, I have a treeview which is populated at run time and here is my xaml code
<StackPanel Orientation="Horizontal">
<Image Source="Properties\accessories-text-editor-6.ico" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" Foreground="Green" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" MouseRightButtonDown="TextBlock_MouseRightButtonDown" >
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="HeadLine" ></MenuItem>
<MenuItem Header="Textblock" ></MenuItem>
<MenuItem Header="Author" ></MenuItem>
<MenuItem Header="PageNumber" ></MenuItem>
<MenuItem Header="RunningTitle" ></MenuItem>
<MenuItem Header="Illustration" ></MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</StackPanel>
what I want is when I right click the textblock that is inside the treeview. the textblock need to be focus. As of now what it does is show the context menu item.
so how do I get the index of the Right clicked textblock? so I can focus to that item.
Thank you
A TextBlock cannot be focused...but you can get a reference to it in the MouseRightButtonDown event handler by casting the sender argument:
private void TextBlock_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock txt = sender as TextBlock;
//do whatever you want with the TextBlock...
}
If you are in the context of a TreeView you may want to select the parent TreeViewItem:
private void TextBlock_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock txt = sender as TextBlock;
TreeViewItem tvi = FindParent<TreeViewItem>(txt);
if (tvi != null)
tvi.IsSelected = true;
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
I've a listview and I want to copy the selected item by selecting the copy command in the context menu. I'm able to create a context menu with the copy command as shown in the image below:
The problem is when I select a row item and right click it, the context menu wouldn't show and I cannot select the copy command to copy the selected item. The context menu will show when I right click at the empty space in the list view.
Here's the code:
.xaml
<ListView x: Name = "DebugLogLb" BorderBrush = "{x:Null}" SelectionMode = "Extended" MouseRightButtonDown = "DebugLogLb_MouseRightButtonDown">
<ListViewItem x: Name = "DebugLogItem">
<ListViewItem.ContextMenu>
<ContextMenu x: Name = "CommandMenu">
<MenuItem Header = "Clear log" Click = "CommandMenuItem_Click"/>
<MenuItem Header = "Copy" Command = "Copy" CommandTarget = "{Binding ElementName=DebugLogItem}"/>
</ContextMenu>
</ListViewItem.ContextMenu>
</ListViewItem>
</ListView >
.xaml.cs:
private void DebugLogLb_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
ContextMenu contextMenu = this.FindName("CommandMenu") as ContextMenu;
contextMenu.PlacementTarget = sender as ListViewItem;
contextMenu.IsOpen = true;
}
private void CommandMenuItem_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem) e.OriginalSource;
switch (menuItem.Header.ToString())
{
case "Clear log":
DebugLogLb.Items.Clear();
break;
default:
break;
}
}
Something like this will let you use the ContextMenu with its MenuItems :
<ListView x:Name = "DebugLogLb" BorderBrush = "{x:Null}" SelectionMode = "Extended" ItemsSource="{Binding items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.ContextMenu >
<ContextMenu x:Name = "CommandMenu">
<MenuItem Header = "Clear log" />
<MenuItem Header = "Copy" Command = "Copy" CommandTarget = "{Binding ElementName=DebugLogItem}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView >
So, define it inside the ItemTemplate in order to be able to use it when selecting each item.
The items collection is defined in code behind :
public ObservableCollection<string> items { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
items = new ObservableCollection<string>();
items.Add("first item");
items.Add("second item");
}
Nothing fancy, just for the sake of example.
One more thing, if you still want it available when clicking on the white space, add a ContextMenu on the ListView too:
<ListView.ContextMenu>
<ContextMenu x:Name = "CommandMenu">
<MenuItem Header = "Clear log" />
<MenuItem Header = "Copy" Command = "Copy" CommandTarget = "{Binding ElementName=DebugLogItem}"/>
</ContextMenu>
</ListView.ContextMenu>
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).
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.
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.
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.