【问题标题】:What can break WPF CommandBindings on a MenuItem?什么可以破坏 MenuItem 上的 WPF CommandBindings?
【发布时间】:2014-09-30 17:45:37
【问题描述】:

我有一些 CommandBindings(在 Window 中)与 MenuItems 一起工作(“工作”是指 executed/canexecute 处理程序被调用),

我还有其他人(在UserControl 中)在分配给Buttons 的Command 属性时工作(调用处理程序)-但在与MenuItems 一起使用时不起作用(处理程序永远不会称为)。

我可以通过将每个绑定复制并粘贴到适当的MenuItem.CommandBindings 中来使MenuItemUserControl 中的CommandBinding 正确交互,如下所示:

<MenuItem
    Header="Select All"
    Command="{StaticResource SelectAllCommand}"
    >
    <MenuItem.CommandBindings>
        <CommandBinding
            Command="{StaticResource SelectAllCommand}"
            Executed="SelectAll_Executed"
            CanExecute="SelectAll_CanExecute"
            />
    </MenuItem.CommandBindings>
</MenuItem>

但这很愚蠢(见下文)。

我还可以通过将UserControl 的命令绑定复制到UserControl 的构造函数中的窗口来使它们工作:

C#

Application.Current.MainWindow.CommandBindings.AddRange(this.CommandBindings);

再一次,这很疯狂,但这似乎暗示着这里有一个上下文因素在起作用。

我将控制 XAML 的相关位复制到以下测试 XAML 中以重现该问题,但该问题未重现。与我从中提取它的生产代码不同,它按您期望的那样工作:它是一个绑定,它是绑定的,它调用方法。但是,将事件处理程序方法绑定到菜单项的命令的完全相同的方法在不同的 UserControl 中的不同(并且无法兼容的更大和更复杂)项目中失败。

XAML:

<UserControl
    x:Class="CommandTest.TestControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d" 
    d:DesignHeight="300"
    d:DesignWidth="300"
    >
    <UserControl.Resources>
        <ResourceDictionary>
            <RoutedUICommand x:Key="TestCommand" />

            <ContextMenu x:Key="TestMenu">
                <MenuItem 
                    Header="_Test"
                    Command="{StaticResource TestCommand}"
                    />
            </ContextMenu>
        </ResourceDictionary>
    </UserControl.Resources>

    <UserControl.CommandBindings>
        <CommandBinding
            Command="{StaticResource TestCommand}"
            Executed="TestCommand_Executed"
            CanExecute="TestCommand_CanExecute"
            />
    </UserControl.CommandBindings>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBox 
            Width="200"
            ContextMenu="{StaticResource TestMenu}"
            />
    </Grid>
</UserControl>

C#:

private void TestCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    MessageBox.Show("Test Command", "Test", MessageBoxButton.OK, 
                    MessageBoxImage.Information);
}

private void TestCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
    e.Handled = true;
}

那么问题是,哪些隐藏因素会导致CommandBinding 静默失败?你怎么调试这个?对于同一控件中的同一命令绑定,为什么我会在 ButtonMenuItem 之间看到完全不同的行为?是因为ContextMenu 是资源吗?但在我的测试代码中,它是一种资源,一切正常。

更新:

Another solution^Wworkaround:将MenuItem.PlacementTarget 显式设置为ContextMenu。嗯。

【问题讨论】:

    标签: wpf xaml data-binding command commandbinding


    【解决方案1】:

    我怀疑测试项目的可视化树与干扰命令路由的生产项目之间存在细微差别。 Routed Commands 沿着可视化树搜索命令处理程序,最多可以采用两条路径。

    来自this MSDN Magazine article

    通常,命令调用程序会在它自己在可视化树中的位置和可视化树的根之间查找命令绑定。如果找到,则绑定的命令处理程序将确定该命令是否已启用,并在调用该命令时调用该命令。如果命令连接到工具栏或菜单内的控件(或者,更一般地,设置 FocusManager.IsFocusScope = true 的容器),那么一些额外的逻辑运行也会沿着可视化树路径从根到焦点命令绑定的元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-19
      • 2014-08-30
      • 2015-07-02
      • 2015-08-21
      • 2011-08-18
      • 2018-07-08
      相关资源
      最近更新 更多