Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Command Target in XAML

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

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?

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

Window 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:

<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:

    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:

<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:

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(); 
    }
}
like image 413
kevindaub Avatar asked Jun 19 '09 00:06

kevindaub


People also ask

What is command target?

The command target is the element on which the command is executed. With regards to a RoutedCommand, the command target is the element at which routing of the Executed and CanExecute starts.

What is the use of ICommand in WPF?

ICommand is an interface between the Presentation & the BusinessLogic layer. Whenever any button is pressed on the screen, XAML has its code-behind ButtonClick event. But in MVVM architecture, there is no room for code-behind to keep the application loosely coupled, so ICommand was introduced.

What is Command design pattern and ICommand in WPF?

The command pattern is a behavioral design pattern. This pattern encapsulates a request as an object that contains all the information about the request, including requests for queues or logs, allowing for much more complex architectures. It even allows operations like undo and redo.

Which property is used to associate a command with the event handlers that implement the command?

Using onevent properties These properties are called to run associated handler code when the event is fired, and may also be called directly by your own code. To set event handler code you can just assign it to the appropriate onevent property.


1 Answers

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.

After doing that, set your Button's CommandTarget to your custom UserControl's 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.

As for the code, you only need to change your ToolBar class. This assumes your MyCommand class inherits from RoutedUICommand. Here's the 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;

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.

like image 195
micahtan Avatar answered Oct 15 '22 08:10

micahtan