Установка цели команды в XAML

Мне трудно понять свойство CommandTarget для RoutedCommand.

По сути, у меня есть несколько статических команд, которые имеют реализации в пользовательском элементе управления (не в окне). Я создаю привязку команд в пользовательском элементе управления. Если я объявлю кнопку в пользовательском контроле, то смогу использовать перенаправленное событие. Однако, когда кнопка находится вне пользовательского контроля, я не могу использовать перенаправленное событие. Я думаю, что командная цель решит мою проблему.

Итак, как мне установить commandtarget для кнопки usercontrol на панели инструментов, чтобы вызывался Container Executed и CanExecuted?

Отредактированный код с изменениями из изменений в Михахтане, но я все еще не могу передать его в CanExecute или Execute.

Окно 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(); 
    }
}

2 ответа

Решение

Если вы хотите использовать CommandTargets, я бы создал CommandTarget DependencyProperty для вашего пользовательского элемента управления UserControl, аналогично тому, как это определено в ButtonBase.

После этого установите CommandTarget вашей кнопки в значение CommandTarget вашего пользовательского элемента управления.

РЕДАКТИРОВАТЬ: Пример кода

Комментарии Руди верны, если вы работаете с архитектурой MVVM - в этом случае хорошо работают RelayCommands или какая-либо другая форма обернутых делегатов. Исходя из вашего примера кода, не похоже, что вы используете этот подход, поэтому мой оригинальный комментарий.

Что касается кода, вам нужно всего лишь изменить свой класс 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>

И вот код позади:

используя 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));
    }
}

Обратите внимание, что я изменил некоторые имена классов / пространства имен в своем тестовом проекте. Вам придется изменить их в соответствии с вашими потребностями.

Вы решили использовать RelayCommand или DelegateCommand? Твой может быть больше подходит для того, что вам нужно?

Для примера использования RelayCommand прочитайте эту статью Джоша

Брайан Нойес также имеет отличную статью, доступную здесь

Другие вопросы по тегам