0

I've used the following method:

<ListView x:Name="itemsListView" ItemsSource="{Binding MyItems}">
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Remove"
        Command="{Binding RemoveItem}"
        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" />
        </ContextMenu>
    </ListView.ContextMenu>
</ListView>

provided by blindmeis here, for creating and binding ContextMenu and it works fine if I first select an item and then right click. If I, however, do not select any item and click anywhere in ListView it still appears and invoke the command with null.

2 Answers2

1

First of all, move your ContextMenu to the Resources, then apply it to the ListView's ContextMenu in a DataTrigger, based on whether the SelectedItem is null or not:

<Window.Resources>
    <ContextMenu x:Key="MyContextMenu">

        <MenuItem Header="Remove"
                  Command="{Binding RemoveItem}"
                  CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" />
    </ContextMenu>
</Window.Resources>
<Grid>
    <ListView x:Name="itemsListView" ItemsSource="{Binding MyItems}">
        <ListView.Style>
            <Style TargetType="{x:Type ListView}">
                <Setter Property="ContextMenu"
                        Value="{StaticResource MyContextMenu}" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding SelectedItem, ElementName=itemsListView}"
                                 Value="{x:Null}">
                        <Setter Property="ContextMenu"
                                Value="{x:Null}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListView.Style>
    </ListView>
</Grid>
SamTh3D3v
  • 9,854
  • 3
  • 31
  • 47
  • This also works. It'd be nice if I could accept both answers as solutions to my problem. –  Nov 21 '19 at 21:45
1

One way to do this is to set the ContextMenu on the ListViewItem instead of the ListView.

This will ensure that the ContextMenu will only display when there is a ListViewItem available. And if the item isn't selected, it will be when the user right-clicks on it.

The only trick here is to deal with a DataContext issue in the ContextMenu. That is done by setting the Tag property of the ListViewItem to the DataContext of the ListView. This will allow the ContextMenu to bind to the RemoveItem command.

<ListView x:Name="ItemsListView"
    Width="200"
    Height="300"
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    ItemsSource="{Binding MyItems}">
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem
                            Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.Tag.RemoveItem}"
                            CommandParameter="{Binding}"
                            Header="Remove" />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
            <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=DataContext}" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

I hope this helps!

Keithernet
  • 2,349
  • 1
  • 10
  • 16