我有一个UserControl我已经构建了包含许多包含TextBlock控件的Border。 TextBlocks的Text属性设置为来自ViewModel对象的数据。
我在UserControl的资源中添加了几个上下文菜单:
<UserControl.Resources>
<ContextMenu x:Key="ContextMenu">
<MenuItem Header="Copy Plate" Command="cs:CarSystemCommands.CopyPlateCommand" />
<MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
</ContextMenu>
<ContextMenu x:Key="TextBoxContextMenu">
<MenuItem Header="_Copy" Command="Copy" />
<MenuItem Header="Copy Plate" Command="cs:CarSystemCommands.CopyPlateCommand" />
<MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
</ContextMenu>
</UserControl.Resources>
我已将对上下文菜单的引用添加到我的TextBlocks中。这是一个例子:
<Border Background="#FFFFFF78"
BorderBrush="Black"
BorderThickness="2"
ContextMenu="{StaticResource TextBoxContextMenu}"
Grid.Column="0"
Margin="5,10,5,5">
<TextBlock FontSize="18"
FontWeight="Bold"
HorizontalAlignment="Center"
Margin="5"
x:Name="Camera"
VerticalAlignment="Center" />
</Border>
最后,我已将CommbandBindings添加到UserControl:
<UserControl.CommandBindings>
<CommandBinding Command="Copy" CanExecute="CopyCommand_CanExecute" Executed="CopyCommand_Executed" />
<CommandBinding Command="cs:CarSystemCommands.CopyPlateCommand" CanExecute="CopyCommand_CanExecute" Executed="CopyPlateCommand_Executed" />
</UserControl.CommandBindings>
到目前为止,我遇到了两个问题:
当我右键单击控件时,我会看到菜单,但选项显示为灰色。我在CopyCommand_CanExecute,CopyCommand_Executed和CopyPlateCommand_Executed方法的开头放置了断点。到目前为止,这些断点仅在一次运行中被击中。我不知道他们为什么会被击中,但不是之前或之后。如何确保每次都调用CanExecute方法?
有一次断点被击中,参数的Source属性不是我认为的控件,它是UserControl。我需要知道UserControl上的哪些TextBlock引发了事件。我该怎么做?
贝
编辑:
UserControl还包含一个ComboBox控件。我发现在我下拉ComboBox后右键单击TextBlocks时,CanExecute方法会运行。我不必在组合框中选择任何东西,我只需要点击它。
任何想法ComboBox可能会做什么,而我的代码不是?
另一件事是在下拉ComboBox之后,Execute事件参数的OriginalSource是ComboBox。我想在几个TextBlocks上使用相同的Copy命令,我需要知道使用哪个上下文菜单,所以我知道哪个TextBlock的Text要复制到剪贴板。救命啊!
答案 0 :(得分:0)
我找到了问题的部分答案。我想出了一种方法,我的代码可以确定从ContextMenu执行哪个TextBlock的Copy命令。我没有为需要此命令的三个TextBlock使用公共ContextMenu,而是为每个TextBlock创建了一个单独的ContextMenu。然后,我将CommandParameter添加到该TextBlock的Copy菜单项,其中包含我要复制的属性的名称。然后,在CopyCommand_Executed事件处理程序中,我检查e.Parameter值的值并将相应控件的值复制到剪贴板。这很有效。
但是,在我选择ComboBox中的内容之前,我的CanExecute事件的问题仍未解决。我仍然需要弄明白这一点。
编辑:
嗯,现在一切似乎都运转正常,包括CanExecute事件。我正在尝试各种必须破坏的东西,但现在我已经让CommandParameter工作了,其他一切似乎都没问题。我打算将此作为答案。
第二次编辑:
嗯,实际上,当我发布这个时,一切都在处理我正在处理的UserControl。但仍有问题。
上面提到的UserControl实际上是嵌入在另一个UserControl中。第一个UserControl的内容包含在StackPanel中;我将StackPanel设置为FocusScope,这似乎是一切都开始工作的时候。
第二个控件在根处有一个StackPanel,里面有一些Grids。第一个Grid包含第一个UserControl和其他一些东西。下面的第二个Grid有两个具有ContextMenus的DataGrids。它的这些ContextMenus现在不能正常工作。
我已将StackPanel作为FocusScope。第一个UserControl上下文菜单不起作用,除非我把它作为FocusScope,所以它也是一个。最后,我制作了将两个DataGrids保存为FocusScope的Grid。
我认为这个问题与FocusScopes有关,但我不知道它是如何相关的,也没有我试过的组合。有什么想法吗?
答案 1 :(得分:0)
我的代码已解决此问题。事实证明,问题在于XAML处理器无法确定命令的目标是什么。也就是说,它无法确定将命令发送到何处。
我能够使用我的代码中的代码修复此问题。我仍然对这个问题的XAML修复感兴趣,但我没有时间研究它。与此同时,我实施的解决方案运行良好。
对于那些感兴趣的人,这里是我写的代码,它设置了命令的目标:
private void FixMenuItems( FrameworkElement element, Func<MenuItem, bool> condition ) {
foreach ( MenuItem menuItem in element.ContextMenu.Items ) {
if ( condition( menuItem ) ) {
menuItem.CommandTarget = this;
}
}
}
要使用该函数,您可以使用您尝试修复该方法的上下文菜单传递对该控件的引用,以及一个以MenuItem
作为参数的函数返回true,如果{{应该将属性设置为当前对象。