1

我是 WPF 新手,正在浏览 .net 4.5 中的专业 WPF 示例。在命令章节中,有一个示例,多个控件可以发送相同的命令。我正在使用 Button、CheckBox 和 MenuItem 来触发 New 命令。

我面临的问题是,如果第一次按下 MenuItem,源显示正确。但是,单击 Button 或 CheckBox 后,单击 MenuItem 会显示最后一个控件 Button 或 CheckBox 的来源,以按下者为准。我找不到我的代码有什么问题,或者为什么 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);
    }
  }
}
4

1 回答 1

3

是的,这是正确的(或者至少它是这样设计的)。路由命令根据您指定的 CommandTarget 开始路由。如果未指定,则引发事件的对象通常使用自身作为起点(因此在本例中为 MenuItem)。因此,如您所料,在这种情况下,路由从 MenuItem 开始。没有任何东西在那里处理它,所以 CommandManager 上升到父链。当它碰到一个焦点范围的元素(如菜单)时,它会检查“父”焦点范围的焦点元素(例如,菜单的父级的焦点范围,在这种情况下是窗口)。如果有一个 FocusedElement(一旦您将一个元素聚焦在窗口的焦点范围内,例如您的按钮、复选框、您可能放在该堆栈面板中的文本框等,就会有一个 FocusedElement。) 然后 CommandManager 开始从该元素路由事件。当它这样做时,它会创建一个新的 ExecutedRoutedEventArgs,其中 OriginalSource 是该起始元素(因此是按钮、复选框、文本框),然后继续沿树向上路由。

因此,当您第一次运行该应用程序时,Window 的 FocusedElement(即您示例中的根焦点范围)为空,因此不需要重新路由,因此 CommandManager 只是继续向上通过菜单的父链,这就是为什么MenuItem 显示为 Source & OriginalSource。当您单击 Button 时,您给了该键盘焦点,并且作为它的一部分,它也成为其焦点范围的逻辑焦点元素(即其包含 FocusScope 的 FocusedElement)。因此,当随后单击 MenuItem 并且 CommandManager 最终到达菜单时,它然后重新路由到 Button(或您在窗口的焦点范围内聚焦的任何内容)并从那里开始向上路由。我说这是意料之中的,因为使用 routed 命令您希望路由通过逻辑集中的元素,例如,

于 2013-04-26T16:53:21.380 回答