C# 在 XAML 中设置命令目标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1015851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:36:56  来源:igfitidea点击:

Setting Command Target in XAML

c#wpfxamlroutedcommand

提问by kevindaub

I am having a hard time understanding the CommandTarget property for a RoutedCommand.

我很难理解 RoutedCommand 的 CommandTarget 属性。

Basically, I have some static commands that have implementations in a user control (not the window). I create a commandbinding in the user control. If I declare the button in the usercontrol, then I am able to use my routed event. However, when the button is outside of the usercontrol, then I cannot use my routed event. I think the command target will solve my issue.

基本上,我有一些静态命令在用户控件(而不是窗口)中有实现。我在用户控件中创建了一个命令绑定。如果我在用户控件中声明按钮,那么我就可以使用路由事件。但是,当按钮在用户控件之外时,我无法使用路由事件。我认为命令目标将解决我的问题。

So how do I set the commandtarget for the toolbar usercontrol's button, so that the Container's Executed and CanExecuted is called?

那么如何为工具栏用户控件的按钮设置 commandtarget,以便调用 Container 的 Executed 和 CanExecuted 呢?

Edited Code with changes from micahtan changes, but I still can't get it to CanExecute or Execute.

使用 micahtan 更改更改的已编辑代码,但我仍然无法将其设置为 CanExecute 或 Execute。

Window XAML:

窗口 XAML:

<Window x:Class="RoutedCommands.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RoutedCommands"
    xmlns:toolbar="clr-namespace:RoutedCommands.Toolbar"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <local:Container Width="100" Height="25" x:Name="MyContainer" />
        <toolbar:Toolbar Width="100" Height="25" CommandTarget="{Binding MyContainer}" />
    </StackPanel>
</Window>

Toolbar XAML:

工具栏 XAML:

<UserControl x:Class="RoutedCommands.Toolbar.Toolbar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RoutedCommands"
    x:Name="MyToolbar"
    Height="300" Width="300">
    <Grid>
        <Button Command="{x:Static local:Commands.MyCommand}" Content="Try Me" CommandTarget="{Binding ElementName=MyToolbar, Path=CommandTarget, Mode=OneWay}" />
    </Grid>
</UserControl>

Toolbar CS:

工具栏 CS:

    public partial class Toolbar : UserControl
    {
        public Toolbar()
        {
            InitializeComponent();
        }

        // Using a DependencyProperty as the backing store for CommandTarget.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandTargetProperty =
                DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(Toolbar), new UIPropertyMetadata(null));

        public IInputElement CommandTarget
        {
            get { return (IInputElement)GetValue(CommandTargetProperty); }
            set { SetValue(CommandTargetProperty, value); }
        }
    }

Container XAML:

容器 XAML:

<UserControl x:Class="RoutedCommands.Container"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RoutedCommands"
    Height="300" Width="300">
    <UserControl.CommandBindings>
        <CommandBinding Command="{x:Static local:Commands.MyCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed" />
    </UserControl.CommandBindings>
    <Grid>
        <Button Command="{x:Static local:Commands.MyCommand}" Content="Click Me" />
    </Grid>
</UserControl>

Container CS:

容器CS:

public partial class Container : UserControl
{
    public Container()
    {
        InitializeComponent();
    }

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        Console.WriteLine("My Command Executed");
    }

    private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        Console.WriteLine("My Command Can Execute");
        e.CanExecute = true;
    }
}

RoutedCommands:

路由命令:

namespace RoutedCommands
{
    public static class Commands
    {
        public static readonly RoutedUICommand MyCommand = new RoutedUICommand(); 
    }
}

采纳答案by micahtan

If you want to use CommandTargets, I would create a CommandTarget DependencyProperty on your custom UserControl, similar to the way it's defined on ButtonBase.

如果您想使用 CommandTargets,我将在您的自定义 UserControl 上创建一个 CommandTarget DependencyProperty,类似于它在 ButtonBase 上的定义方式。

After doing that, set your Button's CommandTarget to your custom UserControl's CommandTarget.

执行此操作后,将您的 Button 的 CommandTarget 设置为您自定义的 UserControl 的 CommandTarget。

EDIT: Code Sample

编辑:代码示例

Rudi's comments are valid if you're doing an MVVM architecture -- RelayCommands or some other form of wrapped delegates work well in that case. Based on your code sample, it didn't look like you were using that approach, hence my original comment.

如果您使用的是 MVVM 架构,Rudi 的评论是有效的——在这种情况下,RelayCommands 或某种其他形式的包装委托工作得很好。根据您的代码示例,您似乎没有使用这种方法,因此是我的原始评论。

As for the code, you only need to change your ToolBar class. This assumes your MyCommand class inherits from RoutedUICommand. Here's the XAML:

至于代码,你只需要改变你的 ToolBar 类。这假设您的 MyCommand 类继承自 RoutedUICommand。这是 XAML:

<UserControl
    x:Class="WPFCommandTarget.CustomToolBar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFCommandTarget"
    x:Name="theControl">
    <Grid>
        <Button
            x:Name="theButton"
            Command="{x:Static local:Commands.MyCommand}"
            CommandTarget="{Binding ElementName=theControl, Path=CommandTarget, Mode=OneWay}"
            Content="Try Me" />
    </Grid>
</UserControl>

And here's the code-behind:

这是代码隐藏:

using System.Windows; using System.Windows.Controls;

使用 System.Windows;使用 System.Windows.Controls;

namespace WPFCommandTarget
{
    /// <summary>
    /// Interaction logic for CustomToolBar.xaml
    /// </summary>
    public partial class CustomToolBar : UserControl
    {
        public CustomToolBar()
        {
            InitializeComponent();
        }

        public IInputElement CommandTarget
        {
            get { return (IInputElement)GetValue(CommandTargetProperty); }
            set { SetValue(CommandTargetProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CommandTarget.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandTargetProperty =
            DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CustomToolBar), new UIPropertyMetadata(null));
    }
}

Please note that I've changed some of the class names/namespaces in my test project. You'll have to change them to suit your needs.

请注意,我更改了测试项目中的一些类名/命名空间。您必须更改它们以满足您的需要。

回答by rudigrobler

Have you concidered to rather use the RelayCommand or DelegateCommand! Thy might be more suited to what you need?

您是否考虑过使用 RelayCommand 或 DelegateCommand!你可能更适合你的需要?

For a example of using RelayCommand, read thisarticle by Josh

有关使用 RelayCommand 的示例,请阅读Josh 的这篇文章

Brian Noyes also have a excellent article available here

Brian Noyes 也有一篇很棒的文章可以在这里找到