命令和菜单

时间:2012-01-26 20:36:33

标签: wpf contextmenu commandbinding

我有一个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>

到目前为止,我遇到了两个问题:

  1. 当我右键单击控件时,我会看到菜单,但选项显示为灰色。我在CopyCommand_CanExecute,CopyCommand_Executed和CopyPlateCommand_Executed方法的开头放置了断点。到目前为止,这些断点仅在一次运行中被击中。我不知道他们为什么会被击中,但不是之前或之后。如何确保每次都调用CanExecute方法?

  2. 有一次断点被击中,参数的Source属性不是我认为的控件,它是UserControl。我需要知道UserControl上的哪些TextBlock引发了事件。我该怎么做?

  3. 编辑:

    UserControl还包含一个ComboBox控件。我发现在我下拉ComboBox后右键单击TextBlocks时,CanExecute方法会运行。我不必在组合框中选择任何东西,我只需要点击它。

    任何想法ComboBox可能会做什么,而我的代码不是?

    另一件事是在下拉ComboBox之后,Execute事件参数的OriginalSource是ComboBox。我想在几个TextBlocks上使用相同的Copy命令,我需要知道使用哪个上下文菜单,所以我知道哪个TextBlock的Text要复制到剪贴板。救命啊!

2 个答案:

答案 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,如果{{应该将属性设置为当前对象。