Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: Binding the command parameter for ListBox ContextMenu to the Selected Item of the ListBox

Is it possible to bind the CommandParameter for a ListBox ContextMenu to the Selected Item of the ListBox? I should say that the ContCommand is in the main window and it is called when the Context Menu item is clicked - however, I need to get the parameter to work properly.

I tried this but the binding fails:

<Window x:Class="ListBoxContextMenu.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"
        xmlns:local="clr-namespace:ListBoxContextMenu"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <StackPanel>
            <TextBlock Text="ListBox here:"/>
            <ListBox ItemsSource="{Binding Items}" MinHeight="100" TabIndex="0" x:Name="LB">
                <ListBox.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Foo" Command="{Binding ContCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}},Path=SelectedItem}"/>
                    </ContextMenu>
                </ListBox.ContextMenu>
            </ListBox>
        </StackPanel>
    </Grid>
</Window>

C# code for MainWindow:

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using MvvmFoundation.Wpf;

    namespace ListBoxContextMenu
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DataContext = this;
                Loaded += (sender, e) => MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                ContCommand = new RelayCommand<object>((object o) =>
                {
                    System.Diagnostics.Debug.WriteLine("Context Menu pressed");
                });
            }

            public ObservableCollection<string> Items { get; set; } = new ObservableCollection<string>{"Fred", "Jim", "Sheila"};
            public RelayCommand<object> ContCommand { get; set; }
        }
    }
like image 423
Adrian S Avatar asked Nov 15 '25 01:11

Adrian S


1 Answers

The ListBox is not a visual ancestor of the ContextMenu because the latter resides in its own visual tree.

But you could bind to the PlacementTarget of the ContextMenu, which is the ListBox.

This works:

<ListBox ItemsSource="{Binding Items}" MinHeight="100" TabIndex="0" x:Name="LB">
    <ListBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Foo" Command="{Binding ContCommand}" 
                              CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}},
                                Path=PlacementTarget.SelectedItem}"/>
        </ContextMenu>
    </ListBox.ContextMenu>
</ListBox>
like image 184
mm8 Avatar answered Nov 17 '25 15:11

mm8



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!