什么是默认命令目标?

时间:2012-05-12 13:04:34

标签: c# wpf command

关于在“WPF控制开发”一书中扮演默认命令目标角色的元素有两种不同的想法:

  

命令目标是命令所在的对象   提高。 ICommandSource接口包含CommandTarget属性   可以设置为特定对象。 默认情况下,命令源   本身被视为命令目标。

     

Page 262» 默认情况下,未设置CommandTarget时,元素   使用键盘焦点。

此外,在此tutorial,我们可以保留菜单项和按钮命令目标未定义,而菜单项(即非按钮)可以真正检测命令目标。那么什么是默认命令目标?!

4 个答案:

答案 0 :(得分:4)

根据一些更不同的测试案例以及@dowhilefor和@hbarck的答案,我得出结论,每个案例都有一个特定的旅行路径。

指定的CommandTarget:它从CommandTarget开始朝向可视树的根元素,以找到绑定命令的第一个(最近的)元素。 (它仅在此路径上查找此元素。)结论:

  1. sender:已绑定命令的CommandTarget容器元素(CommandBinding)。
  2. e.source:指定为CommandTarget的元素。
  3. 未指定的CommandTarget:它从聚焦(在CommandSource范围内)的元素开始,朝向可视树的根元素,以找到绑定命令的第一个(最近的)元素。在这种情况下,聚焦元素将被确定为CommandTarget。结论:

    1. sender:已绑定命令的focus元素的容器(带CommandBinding标记)。
    2. e.Source:焦点元素。

答案 1 :(得分:2)

脱离上下文我不明白第一个突出显示的句子意味着什么,但我认为它错了。另一方面,第二句是对的

MSDN:

  

如果未定义命令目标,则具有键盘焦点的元素   将用作命令目标。

如果您希望命令对某些内容进行操作(如当前聚焦文本框上的粘贴命令),这将非常有用。您希望粘贴命令始终有效,无论哪个文本框或其他控件都有焦点,这都可以实现。值得指出的是,关于菜单,还有另一个要记住的概念叫做FocusScope。在WPF中命令有时会很棘手,考虑一个不占用文本框焦点的保存按钮,因此不刷新Text属性(因为它只更新了focuslost上的目标绑定)。但请记住,CommandTarget仅适用于RoutedCommands,而不适用于“简单”ICommands。

关于你的教程视频,还没有看到它:这个概念适用于所有不接受键盘焦点的CommandSource。

总而言之:只要命令是RoutedCommand,CommandTarget就是当前键盘聚焦元素,否则会被忽略。

答案 2 :(得分:1)

这里似乎缺少一点:给定Command的CommandTarget只能是为该命令定义CommandBinding的对象。

编辑:澄清并更正以下段落,以免在系统中留下误导性信息。

命令路由是事件路由的一种特殊情况,即在逻辑树中上下移动的事件:实现ICommandSource接口的控件,如InputBindings,Buttons或MenuItems,是CommandSources。如果他们引发命令,则会导致RoutedEvent从CommandTarget开始。这通常是具有键盘焦点的元素。事件沿逻辑树向上移动,直到到达根。虽然通常处理命令的第一个元素赢得并停止路由进程,但是沿此方式使用命令CommandBindings的所有元素都有机会处理该命令。这甚至可能是CommandSource本身,如果它有命令的CommandBinding,这可能是你的第一个引用。如果元素处理事件,则sender参数将是定义CommandBinding的元素,而事件的RoutedEventArgs的Source属性将是事件startet路由的元素,即CommandTarget。

为了完成混淆,ICommandSource接口定义了一个名为CommandTarget的属性。此属性适用于您希望短路命令路由的情况,并且无论键盘焦点位于何处,都需要特殊控制来处理命令。在这种情况下,您可以在Button或MenuItem上编写类似CommandTarget =“{Binding ElementName = MyCommandTargetControl}”的内容。同样,您必须确保此控件具有Command的CommandBinding,否则将永久禁用Command。

答案 3 :(得分:1)

我想我只是明白这意味着什么:

  

如果元素是可聚焦的,则它无法检测未定义的路由命令   自动定位。

如果一个元素是可聚焦的,这意味着它在激活时始终具有键盘焦点以便发出命令。因此,如果它具有Command的CommandBinding,它将始终自己处理它,如果它没有,它将始终被禁用。

但是,你可以通过在控件的容器上将FocusManager.IsFocusScope设置为true来解决这个问题,就像在这个XAML中一样:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:CommandRouting"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Menu IsMainMenu="True">
            <MenuItem x:Name="TestMenuItem" Command="{x:Static my:MainWindow.TestCommand}"/>
        </Menu>
        <GroupBox x:Name="CommandBindingOnControlsGroupBox" Header="CommandBinding on Controls" Grid.Row="1">
            <StackPanel>
            <Button x:Name="CommandBindingOnButtonButton" Command="{x:Static my:MainWindow.TestCommand}" Content="CommandBinding on Button">
               <Button.CommandBindings>
                    <CommandBinding Command="{x:Static my:MainWindow.TestCommand}" Executed="CommandBinding_Executed" PreviewExecuted="CommandBinding_Executed"/>
                </Button.CommandBindings>
            </Button>
                <TextBox x:Name="CommandBindingOnTextBoxTextBox">
                    <TextBox.CommandBindings>
                        <CommandBinding Command="{x:Static my:MainWindow.TestCommand}" Executed="CommandBinding_Executed"/>
                    </TextBox.CommandBindings>
                    <TextBox.InputBindings>
                        <!-- provide alternate keyboard shortcut -->
                        <KeyBinding Key="{x:Static Key.P}" Modifiers="{x:Static ModifierKeys.Control}" Command="{x:Static my:MainWindow.TestCommand}"/>
                    </TextBox.InputBindings>
                </TextBox>
                <Button x:Name="CommandTargetOnButtonButton" Command="{x:Static my:MainWindow.TestCommand}" Content="CommandTarget on Button" CommandTarget="{Binding ElementName=CommandBindingOnControlsGroupBox}">
                    <Button.CommandBindings>
                        <CommandBinding Command="{x:Static my:MainWindow.TestCommand}" Executed="CommandBinding_Executed"/>
                    </Button.CommandBindings>
                </Button>
            </StackPanel>
        </GroupBox>
        <GroupBox x:Name="CommandBindingOnContainerGroupBox" Header="CommandBinding on Container" Grid.Row="2">
            <GroupBox.CommandBindings>
                <CommandBinding Command="{x:Static my:MainWindow.TestCommand}" PreviewExecuted="CommandBinding_Executed"/>
            </GroupBox.CommandBindings>
            <StackPanel x:Name="CommandBindingOnInnerContainerStackPanel">
                <StackPanel.CommandBindings>
                    <CommandBinding Command="{x:Static my:MainWindow.TestCommand}" Executed="CommandBinding_Executed"/>
                </StackPanel.CommandBindings>
                <Button x:Name="CommandBindingOnContainerButton" Command="{x:Static my:MainWindow.TestCommand}" Content="CommandBinding on Two Containers">
                </Button>
                <TextBox x:Name="CommandBindingOnContainerTextBox">
                    <TextBox.InputBindings>
                        <!-- provide alternate keyboard shortcut -->
                        <KeyBinding Key="{x:Static Key.P}" Modifiers="{x:Static ModifierKeys.Control}" Command="{x:Static my:MainWindow.TestCommand}"/>
                    </TextBox.InputBindings>
                </TextBox>
            </StackPanel>
        </GroupBox>
        <GroupBox x:Name="OtherFocusScopeGroupBox" FocusManager.IsFocusScope="True" Header="Other FocusScope, No CommandBindings" Grid.Row="3">
            <StackPanel >
                <Button x:Name="OtherFocusScopeButton" Command="{x:Static my:MainWindow.TestCommand}" Content="Other FocusScope">
                </Button>
                <TextBox x:Name="OtherFocusScopeTextBox">
                    <TextBox.CommandBindings>
                        <CommandBinding Command="{x:Static my:MainWindow.TestCommand}" Executed="CommandBinding_Executed"/>
                    </TextBox.CommandBindings>
                    <TextBox.InputBindings>
                        <!-- provide alternate keyboard shortcut -->
                        <KeyBinding Key="{x:Static Key.P}" Modifiers="{x:Static ModifierKeys.Control}" Command="{x:Static my:MainWindow.TestCommand}"/>
                    </TextBox.InputBindings>
                </TextBox>
            </StackPanel>
        </GroupBox>
    </Grid>
</Window>