How do I right click on a Context Menu button in WPF?
I am working on a WPF error logging application where when the user enters a new connection string, a connection button is created and displayed as a complex list in the sidebar.
I want to right click on these connection buttons to show the context menu of the button for View, Edit, Delete .
My MainWindow.xaml Sidebar Grid looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="318*" />
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
<StackPanel Name="listConnections" Grid.Column="0" Background="#4682b4" Margin="0,0,0,-0.2" >
</StackPanel>
</ScrollViewer>
</TabControl>
</Grid>
And I call Stackpanel listConnections
in my MainWindow.xaml.cs like this
public MainWindow()
{
InitializeComponent();
GetUserData();
//Button to create new connection
listConnections.Children.Add(new NewConnectionButton(this));
this.Closed += new EventHandler(MainWindow_Close);
}
WPF Right Click Event I tried to follow this link to create a right click event but it doesn't work for me. Can someone please help me on this please?
source to share
You have to put the context menu inside the button resources like
<NewConnectionButton.Resources>
<ContextMenu x:Key="connectionButtonContext" StaysOpen="true">
<MenuItem Header="Add" Click="InternalAddButton_Click"/>
<MenuItem Header="Delete" Click="InternalDeleteButton_Click"/>
<MenuItem Header="Edit" Click="InternalEditButton_Click"/>
</ContextMenu>
</NewConnectionButton.Resources>
This code should be inside NewConnectionButton
UserControl. The code in C # UserControl sign these events and publish them ( InternalAddButton_Click
, InternalDeleteButton_Click
, InternalEditButton_Click
), who uses a button. Then sign them into your MainWindow.
source to share
I would do the following here:
- create a context menu separately and assign it to each "connection" object in the user interface
- handle
MenuItem.Click
picks an event for each menu item - allow the selected item in the list and process it accordingly
MVVM and all of this is fine, of course, but this simple approach is at least a good place to start:
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<!-- Having CommandParameter is crucial here -->
<ContextMenu x:Key="contextMenu">
<MenuItem Header="View"
Click="View_OnClick"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}"/>
<MenuItem Header="Edit"
Click="Edit_OnClick"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}" />
<MenuItem Header="Delete"
Click="Delete_OnClick"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}"/>
</ContextMenu>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="318*" />
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
<StackPanel Name="listConnections" Grid.Column="0" Background="#4682b4" Margin="0,0,0,-0.2" >
<Button Click="BtnAdd_OnClick">New Connection</Button>
</StackPanel>
</ScrollViewer>
</Grid>
</Window>
Code for:
using System;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication7
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private static Label FindClickedItem(object sender)
{
var mi = sender as MenuItem;
if (mi == null)
{
return null;
}
var cm = mi.CommandParameter as ContextMenu;
if (cm == null)
{
return null;
}
return cm.PlacementTarget as Label;
}
private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
{
listConnections.Children.Add(new Label
{
Content = "New Connection",
ContextMenu = (ContextMenu)Resources["contextMenu"]
});
}
private void View_OnClick(object sender, RoutedEventArgs e)
{
var clickedItem = FindClickedItem(sender);
if (clickedItem != null)
{
MessageBox.Show(" Viewing: " + clickedItem.Content);
}
}
private void Edit_OnClick(object sender, RoutedEventArgs e)
{
var clickedItem = FindClickedItem(sender);
if (clickedItem != null)
{
string newName = "Connection edited on " + DateTime.Now.ToLongTimeString();
string oldName = Convert.ToString(clickedItem.Content);
clickedItem.Content = newName;
MessageBox.Show(string.Format("Changed name from '{0}' to '{1}'", oldName, newName));
}
}
private void Delete_OnClick(object sender, RoutedEventArgs e)
{
var clickedItem = FindClickedItem(sender);
if (clickedItem != null)
{
string oldName = Convert.ToString(clickedItem.Content);
listConnections.Children.Remove(clickedItem);
MessageBox.Show(string.Format("Removed '{0}'", oldName));
}
}
}
}
This is how it looks:
Hope it helps
source to share