按钮单击时的 ContextMenu 不触发命令 [英] ContextMenu on button click not firing command
问题描述
这里有一个问题.
我在单击按钮时显示上下文菜单,菜单命令绑定到视图模型中的 ICommand
.菜单显示在按钮单击以及右键单击上.问题是当我单击按钮然后单击上下文菜单时菜单单击没有触发,但是当我右键单击按钮然后单击菜单时,我可以确认菜单正在工作.
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.
推荐答案
PlacementTarget
is null
当您手动设置 ContextMenu.IsOpen
属性时,因为只有在通过右键单击目标控件打开后才将其设置为实际值.(PopUpService
类负责将此值设置为实际目标).
PlacementTarget
is null
when you manually set ContextMenu.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).
由于 PlacementTarget
为 null
,如果您通过 Storyboard
打开它,则绑定无法解析其绑定的实际命令
Since PlacementTarget
is null
in case when you open it via Storyboard
, binding is not able to resolve actual command it's binded to.
因此,问题是您需要将 Button
的 DataContext
传递给 MenuItem
以便解决绑定.(MenuItem
与按钮的可视化树不同).这可以通过两种方式实现:
So, issue is you need to pass on the DataContext
of Button
to the MenuItem
so that binding can be resolved. (MenuItem
are not is same visual tree as that of button). That can be achieved via two ways:
使用 x:Reference
(在 WPF 4.0 及更高版本中可用)但您需要声明虚拟控件,以便可以引用它以获取 DataContext代码>,
Visibility
设置为 Collapsed
.
<FrameworkElement x:Name="dummyControl" Visibility="Collapsed"/>
<Button Width="100" Height="30" Name="cmButton">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="New Layout Element..."
Command="{Binding Path=DataContext.SubmitBtn,
Source={x:Reference dummyControl}}" />
</ContextMenu>
</Button.ContextMenu>
</Button>
<小时>
另一个有趣的事情是 Freezable
对象继承 DataContext
即使它们不位于 VisualTree
中,所以我们可以使用这个特性来克服需要继承DataContext
的情况.
Another interesting thing is Freezable
objects inherit DataContext
even if they don't lie in VisualTree
so we can use this feature to overcome situations where we need to inherit DataContext
.
首先我们需要创建继承自Freezable的类
并暴露可以绑定到的DP:
First we need to create class inheriting from Freezable
and exposing DP which can be bind to:
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
}
现在我们可以像这样在 XAML 中使用它:
Now we can use it in XAML like this:
<Button Width="100" Height="30" Name="cmButton">
<Button.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}"/>
</Button.Resources>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="New Layout Element..."
Command="{Binding Path=Data.SubmitBtn,
Source={StaticResource proxy}}" />
</ContextMenu>
</Button.ContextMenu>
</Button>
这篇关于按钮单击时的 ContextMenu 不触发命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!