Reputation: 760
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.
Upvotes: 13
Views: 21418
Reputation: 43
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>
Upvotes: 1
Reputation: 4742
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>
Upvotes: 35