UserControl 中的 RoutedCommand 未按预期工作

RoutedCommand in UserControl is not working as expected

我正在尝试在我的 UserControls 中使用 RoutedCommands,灵感来自 Josh Smith 的这篇文章。

https://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/

我做的和文章中的例子有点不同,在Usercontrol中定义了RoutedCommand和CommandBindings。

现在我正尝试在我的主窗口中使用它。这样通过点击Button,UserControl中的Command就被执行了。不幸的是,我得到的是一个禁用的按钮。

Foo_CanExecute() 方法从未执行。

<UserControl x:Class="RoutedCommandTest.ViewControl"
             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" 
             xmlns:local="clr-namespace:RoutedCommandTest"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.CommandBindings>
        <CommandBinding
            Command="{x:Static local:ViewControl.Foo}"
            PreviewCanExecute="Foo_CanExecute"
            PreviewExecuted="Foo_Executed"
        />
    </UserControl.CommandBindings>
    <Grid>

    </Grid>
</UserControl>

在ViewControl.xaml.cs

    public static readonly RoutedCommand Foo = new RoutedCommand();

    void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    void Foo_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("The Window is Fooing...");
    }

    public ViewControl()
    {
        InitializeComponent();
    }

在MainWindow.xaml中:

<Window x:Class="RoutedCommandTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:RoutedCommandTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <local:ViewControl/>
        <Button Content="Foo" Margin="0 5" Command="{x:Static local:ViewControl.Foo}"/>
    </Grid>
</Window>

您的命令在用户控件中,而按钮在主窗口中。

其中可能包含您的用户控件。

喜欢冒泡和路由事件(用于驱动它们)。

已执行查找将可视化树向上冒泡到绑定的命令。

PreviewExecuted 查找将可视化树向下传送到绑定的命令。

由于您的按钮位于用户控件的父级中,我不确定冒泡或隧道是否有效。

但是隧道将是 PreviewExecuted 和 PreviewCanExecute。

https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.commandbinding.previewexecuted?view=netframework-4.8

https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.commandbinding.previewcanexecute?view=netframework-4.8

要正确执行路由命令可能非常棘手。

有时您需要做的一件事是绑定 commandtarget 以告诉它去哪里查看。

例如:

    <Grid>
      <local:UserControl1 x:Name="UC1" Height="60" Width="100"/>
      <Button Content="Foo" TextElement.FontSize="30" Command="{x:Static local:UserControl1.Foo}"
              CommandTarget="{Binding ElementName=UC1}"
              />
    </Grid> 

适合我。

我很少发现它们有用 - 这是使它们不如您最初想象的有用的方面之一。

编辑:

也许值得一提的是,与常规 icommand 相比,这些命令没有吸引力。您需要使用静态,这意味着它只适用于非常通用的命令,或者您需要将在代码后面的事件处理程序。

另一方面。

如果您要编写的内容必须与具有焦点的内容通用。就像说一个带有多个文本框的文本编辑器,你正在做文本操作。路由命令可能是合适的。不过,我在开发的应用程序中从未遇到过这样的要求。