WPF:";应用程序命令。新的“;在菜单项的情况下显示不正确的源

WPF:";应用程序命令。新的“;在菜单项的情况下显示不正确的源,wpf,menuitem,Wpf,Menuitem,我是WPF新手,正在浏览.NET4.5中的专业WPF示例。在“命令”一章中,有一个示例,其中多个控件可以发送相同的命令。我正在使用按钮、复选框和菜单项来触发新命令 我面临的问题是,如果第一次按下MenuItem,则源代码显示正确。但是,单击按钮或复选框后,单击菜单项会显示最后一个控件按钮或复选框的来源,以按下的为准。我找不到我的代码有什么问题,也找不到为什么在WPF中MenuItem会显示这种行为 下面是代码 <Window x:Class="WpfApplication1.Command

我是WPF新手,正在浏览.NET4.5中的专业WPF示例。在“命令”一章中,有一个示例,其中多个控件可以发送相同的命令。我正在使用按钮、复选框和菜单项来触发新命令

我面临的问题是,如果第一次按下MenuItem,则源代码显示正确。但是,单击按钮或复选框后,单击菜单项会显示最后一个控件按钮或复选框的来源,以按下的为准。我找不到我的代码有什么问题,也找不到为什么在WPF中MenuItem会显示这种行为

下面是代码

<Window x:Class="WpfApplication1.CommandSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="CommandSample" Height="300" Width="300">
  <Window.CommandBindings>
    <CommandBinding Command="New" Executed="CommandBinding_Executed" />
  </Window.CommandBindings>
  <StackPanel>
    <Button Command="New" MaxWidth="80" MaxHeight="30" Content="{x:Static ApplicationCommands.New}" />
    <Menu MaxHeight="30" VerticalAlignment="Top">
      <MenuItem Header="File">
        <MenuItem Command="New"></MenuItem>
      </MenuItem>
    </Menu>
    <CheckBox Command="New"></CheckBox>

  </StackPanel>
</Window>

namespace WpfApplication1 {
  public partial class CommandSample: Window {
    public CommandSample() {
      InitializeComponent();
    }
    private void CommandBinding_Executed(object sender,ExecutedRoutedEventArgs e)
    {
      MessageBox.Show("New Command launched by " + e.Source);
    }
  }
}

命名空间WpfApplication1{
公共部分类CommandSample:Window{
公共命令示例(){
初始化组件();
}
已执行私有无效命令绑定(对象发送方,已执行路由目标)
{
MessageBox.Show(“由“+e.Source”启动的新命令);
}
}
}
是的,这是正确的(或者至少它是这样设计的)。路由命令根据指定的命令目标开始路由。如果未指定,则引发事件的对象通常会将自身用作起点(在本例中,MenuItem也是如此)。因此,正如您所料,在本例中,路由从MenuItem开始。在那里没有任何东西可以处理它,因此CommandManager在父链上运行。当它点击一个作为聚焦镜的元素(如菜单)时,它会检查“父”聚焦镜的FocusedElement(例如,在本例中是窗口的菜单父级的聚焦镜)。如果存在FocusedElement(当您聚焦了窗口焦点范围中的某个元素(例如按钮、复选框、您可能放入该stackpanel的文本框等),则CommandManager将开始从该元素路由事件。当它这样做时,它会创建一个新的ExecutedRoutedEventArgs,其中OriginalSource是起始元素(因此按钮、复选框、文本框),然后继续向上路由树


因此,当您第一次运行应用程序时,窗口的FocusedElement(在您的示例中是根焦点作用域)为空,因此不需要重新路由,因此CommandManager只是继续沿着父链向上移动,经过菜单,这就是MenuItem显示为Source&OriginalSource的原因。当你点击按钮时,你给了键盘焦点,作为它的一部分,它也成为了聚焦范围的逻辑聚焦元素(即,包含聚焦范围的FocusedElement)。因此,当菜单项随后被单击,CommandManager最终到达菜单时,它会重新路由到按钮(或在窗口的聚焦镜中聚焦的任何东西),并从那里开始路由。我说这是预期的,因为使用routed命令,您希望路由通过逻辑聚焦的元素,例如,菜单项的Cut命令将触发窗口中具有聚焦的文本框的剪切。

太好了,非常感谢您的详细解释。这就是原因。我想给+1,但我是新的,没有15个代表,所以它不允许我。但一旦我达到这个目标,我肯定会:)