Here is a problem.
I am displaying context menu on a button click and the menu command is bind to ICommand
in the view model. Menu is displaying on the button click as well as on the right click. The problem is menu click is not firing when I click button and then click context menu, but I can confirm that menu is working when I right click on button and then click on menu.
<Button Grid.Row="3" Width="500" Height="30" Name="cmButton" >
Button with Context Menu
<Button.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Mode=Self}}" >
<MenuItem DataContext="{Binding}" Header="New Layout Element..." Command="{Binding Path=SubmitBtn}" />
</ContextMenu>
</Button.ContextMenu>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I can confirm there is nothing wrong in my view model because command is firing when I do right click on button then click on context menu.
It's happened because the
DataContext
ofContextMenu
isnull
, you just need set him on event click fromButton
. Look the sample:XAML:
BEHIND CODE
I hope help
PlacementTarget
isnull
when you manually setContextMenu.IsOpen
property because it is set to actual value only once it's open by right clicking on target control. (PopUpService
class is responsible for setting this value to actual target).Since
PlacementTarget
isnull
in case when you open it viaStoryboard
, binding is not able to resolve actual command it's binded to.So, issue is you need to pass on the
DataContext
ofButton
to theMenuItem
so that binding can be resolved. (MenuItem
are not is same visual tree as that of button). That can be achieved via two ways:Using
x:Reference
(available in WPF 4.0 and higher) but you need to declare dummy control so that it can be referenced to getDataContext
withVisibility
set toCollapsed
.Another interesting thing is
Freezable
objects inheritDataContext
even if they don't lie inVisualTree
so we can use this feature to overcome situations where we need to inheritDataContext
.First we need to
create class inheriting from Freezable
and exposing DP which can be bind to:Now we can use it in XAML like this: