Вопрос по c#, wpf, xaml – Установка цели команды в XAML

6

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

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

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

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

Окно XAML:

<code><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>
</code>

Панель инструментов XAML:

<code><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>
</code>

Панель инструментов CS:

<code>    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); }
        }
    }
</code>

Контейнер XAML:

<code><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>
</code>

Контейнер CS:

<code>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;
    }
}
</code>

RoutedCommands:

<code>namespace RoutedCommands
{
    public static class Commands
    {
        public static readonly RoutedUICommand MyCommand = new RoutedUICommand(); 
    }
}
</code>
Я еще не смог получить ответ на свой вопрос, но я пытаюсь работать с тем, что у меня есть до сих пор. kevindaub
Написал некоторый код, который должен заставить ваш сценарий работать. micahtan
Это не очень помогло. Я попробую еще немного сегодня вечером. kevindaub

Ваш Ответ

2   ответа
8

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

После этого установите в качестве значения CommandTarget для кнопки свой собственный уровень CommandTarget для UserControl.

EDIT: Code Sample

Комментарии Руди действительны, если вы выполняете архитектуру 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));
    }
}

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

Не могли бы вы предоставить небольшой пример кода или направление? kevindaub
1

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

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

Брайан Нойес также имеет отличную статью в наличииВот

DelegateCommand? Это часть .Net или дополнение? kevindaub
Команды Relay / DelegateCommands не являются частью фреймворка ... Получите его из статьи Джоша или скачайте Prism! Relay / DelegateCommand вообще не полагаются на визуальное дерево ... Вы даете каждой команде делегат для выполнения, и это все ...
@rudigrobler - вы уверены, что RelayCommands будет работать в этом случае? Его пример кода содержит Container и ToolBar как братьев и сестер без ссылок между ними.

Похожие вопросы