在XAML中设置命令目标(Setting Command Target in XAML)

2019-07-28 23:36发布

我有一个很难理解的的RoutedCommand的CommandTarget财产。

基本上,我有具有在用户控制(未窗口)实现一些静态命令。 我创建的用户控件的CommandBinding。 如果我在用户控件声明按钮,然后我可以用我的路由事件。 然而,当按钮是用户控件之外,那么我不能用我的路由事件。 我觉得命令目标将解决我的问题。

所以,我怎么设置工具栏用户控件的按钮commandtarget,使容器的执行,CanExecuted叫?

编辑的代码与micahtan的变化而变化,但我仍然不能得到它CanExecute或执行。

窗口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>

工具栏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>

工具栏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); }
        }
    }

集装箱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>

集装箱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(); 
    }
}

Answer 1:

如果你想使用CommandTargets,我会在你的自定义用户控件,类似于它的上ButtonBase定义方式创建CommandTarget的DependencyProperty。

这样做后,设定按钮的CommandTarget到您的自定义用户控件的CommandTarget。

编辑:代码示例

鲁迪的评论是有效的,如果你正在做一个MVVM体系结构 - RelayCommands或包裹代表的一些其他形式在这种情况下正常工作。 基于您的代码示例,它看起来并不像你使用这种方法,因此,我原来的评论。

至于代码,你只需要改变你的工具栏类。 这是假设你的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>

而这里的代码隐藏:

使用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));
    }
}

请注意,我在我的测试项目改变了一些类名称/命名空间。 你必须改变他们,以满足您的需求。



Answer 2:

你有没有concidered到,而使用RelayCommand或DelegateCommand! 你可能会更适合你需要什么?

对于使用RelayCommand的例子,请阅读此文章由Josh

布赖恩·诺伊斯也有一个可用的优秀文章在这里



文章来源: Setting Command Target in XAML