Question

I have a context menu - problem is I need it to only open when a listviewitem is clicked. Right now it will open if I click anywhere in the listview or in the header.

<ListView> 
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem Header="More Info" Command="{Binding MoreInfo}" />
        </ContextMenu>
     </ListView.ContextMenu>
     <ListView.View> 
         <GridView> 
           <!-- columns and stuff here -->
         </GridView>
     </ListView.View>
 </ListView>

I have tried adding the ContextMenu as a resource and applying it as a style, but this breaks the command (clicking on More Info should open a dialog window, doesnt work this way)

<ListView.Resources>
    <ContextMenu x:Key="ItemContextMenu">
        <MenuItem Header="More Info" Command="{Binding MoreInfo}" Background="WhiteSmoke" />
    </ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}" >
        <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
    </Style>
</ListView.ItemContainerStyle>

So not sure how to restrict the context menu to only the listviewitem and have the command work.

Was it helpful?

Solution

Use the RelativeSource in the command binding in the template, and it will work:

<ListView.Resources>
    <ContextMenu x:Key="ItemContextMenu">
        <MenuItem Header="More Info" Command="{Binding Path=DataContext.MoreInfo, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Background="WhiteSmoke" />
    </ContextMenu>
</ListView.Resources>

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}" >
        <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
    </Style>
</ListView.ItemContainerStyle>

OTHER TIPS

Expanding on this very helpful post...If your ContextMenu has custom buttons or other objects within a ControlTemplate, I have combined the answer above with the answer from Closing ContextMenu with Templated MenuItems so that when a user clicks on the Button, the ContextMenu closes normally only using XAML. This took about 10 hours to put together. Hope it saves you time. Supports MVVM ICommand usage. I also used the Style for the ContextMenu from [this post][2] to elminate the 90's look.

<ListView.Resources>
    <ContextMenu x:Key="ItemContextMenu" Style="{StaticResource HorizontalContextMenu}">
        <MenuItem>
            <MenuItem.Template>
                <ControlTemplate>
                    <Grid MinHeight="50" MinWidth="50">
                        <Button Style="{StaticResource CloseAppButton}" Command="{Binding Path=DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" >
                            <Button.Triggers>
                                <EventTrigger RoutedEvent="Button.Click">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContextMenu.IsOpen)" Storyboard.Target="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}">
                                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <sys:Boolean>False</sys:Boolean>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </Button.Triggers>
                        </Button>
                    </Grid>
                </ControlTemplate>
            </MenuItem.Template>
        </MenuItem>

        <MenuItem>
            <MenuItem.Template>
                <ControlTemplate>
                    <Grid MinHeight="50" MinWidth="50">
                        <Button Style="{StaticResource AddButton}" Command="{Binding Path=DataContext.TestCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" >
                            <Button.Triggers>
                                <EventTrigger RoutedEvent="Button.Click">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContextMenu.IsOpen)" Storyboard.Target="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}">
                                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <sys:Boolean>False</sys:Boolean>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </Button.Triggers>
                        </Button>
                    </Grid>
                </ControlTemplate>
            </MenuItem.Template>
        </MenuItem>

        <MenuItem>
            <MenuItem.Template>
                <ControlTemplate>
                    <Grid MinHeight="50" MinWidth="50">
                        <Button Style="{StaticResource PluginInfoButton}" Command="{Binding Path=DataContext.TestCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" >
                            <Button.Triggers>
                                <EventTrigger RoutedEvent="Button.Click">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContextMenu.IsOpen)" Storyboard.Target="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}">
                                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <sys:Boolean>False</sys:Boolean>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </Button.Triggers>
                        </Button>
                    </Grid>
                </ControlTemplate>
            </MenuItem.Template>
        </MenuItem>
    </ContextMenu>

</ListView.Resources>
<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}" >
        <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    </Style>
</ListView.ItemContainerStyle>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top