Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make right click Button Context menu in WPF?

Tags:

c#

wpf

xaml

I am working on a WPF error logging app, where when a user enters a new connection string, a connection button is created and shown as stacked list on the sidebar.

I want to make a right click event on those connection buttons to show a Button context menu for View, Edit, Delete.

My MainWindow.xaml Sidebar grid is 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 am calling the 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);
}

Right-Click event WPF I tried to follow this link to create the right click event, but it is not working out for me. Can someone please assist me in this please?

like image 574
StraightUp Avatar asked Apr 21 '17 16:04

StraightUp


1 Answers

What I'd do here would be the following:

  • create context menu separately and assign it to every "connection" object on the UI
  • handle MenuItem.Click clicks event for every menu item
  • resolve the clicked item in a list and process it respectively

MVVM and all that is certainly good but this straightforward approach is at least 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-behind:

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 like:

about to click edit

after clicking on edit

Hope this helps

like image 89
alex.b Avatar answered Nov 03 '22 21:11

alex.b