justdruit
justdruit

Reputation: 55

WPF, ApplicationCommands, RoutedUICommand and CommandBindings

Hi I am having trouble with WPF creating a RoutedUICommand that works similar to an ApplicationCommand. Ideally I want to have a single 'Duplicate' MenuItem that works with two different UserControls. Whether or not the MenuItem is active will depend on which UserControl is selected and if the UserControl contains a selected object (the same way cut, copy and past work on different textboxes, etc).

As per this StackOverflow, question I have created the static class below:

namespace App.Classes
{
    public static class myCommands
    {
        private static readonly RoutedUICommand _duplicateCmd = new RoutedUICommand("Duplicate", "Duplicate", typeof(myCommands));

        public static RoutedUICommand Duplicate
        {
            get { return _duplicateCmd; }
        }
    }
}

In the main Window's XAML file I have added a reference to the class's namespace and a KeyBinding to the command.

<Window x:Class="GUI.App.Views.Windows.wndMain"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:classes="clr-namespace:App.Classes">

<Window.InputBindings>
    <KeyBinding Key="D" Modifiers="Control" Command="{Binding classes:myCommands.Duplicate}" />
</Window.InputBindings>

In the MenuItem I have added a Command binding to the 'Duplicate' command

<MenuItem Name="mnCopy" Header="Copy" Command="ApplicationCommands.Copy" InputGestureText="Ctrl+C" />      
<MenuItem Name="mnDuplicate" Header="Duplicate" Command="{Binding classes:myCommands.Duplicate}" InputGestureText="Ctrl+D"/>

And finally in each of my UserControls I have added CommandBindings to the 'Duplicate' and other ApplicationCommands.

<UserControl.CommandBindings> 
    <CommandBinding Command="ApplicationCommands.Copy" Executed="CommandBinding_Copy" CanExecute="CommandBindingCanExecute_Copy" />
    <CommandBinding Command="classes:myCommands.Duplicate" Executed="CommandBinding_DuplicateControls" CanExecute="CommandBindingCanExecute_DuplicateControls" />
</UserControl.CommandBindings>

The code-behind for my Executed and CanExecute for each of the UserControls is

/// <summary>                                                                                                   
///                                                                                                             
/// </summary>                                                                                                  
public void CommandBinding_Copy(Object sender, ExecutedRoutedEventArgs e)
{
    _viewModel.Copy();
}

/// <summary>                                                                                                   
///                                                                                                             
/// </summary>                                                                                                  
public void CommandBinding_Duplicate(Object sender, ExecutedRoutedEventArgs e)
{
    _viewModel.Duplicate();
}

/// <summary>                                                                                                   
///                                                                                                             
/// </summary>                                                                                                  
public void CommandBindingCanExecute_Copy(Object sender, CanExecuteRoutedEventArgs e)
{
    _viewModel.CanExecute_Copy();
}

/// <summary>                                                                                                   
///                                                                                                             
/// </summary>                                                                                                  
public void CommandBindingCanExecute_Duplicate(Object sender, CanExecuteRoutedEventArgs e)
{
    _viewModel.CanExecute_Duplicate();
}

This works perfectly for my ApplicationCommands and the appropriate Executed and CanExecute get called depending upon which UserControl is selected. But I can't get it to work with my 'Duplicate' RoutedUICommand. Does anybody know what I'm doing wrong or am missing? Will be grateful for any help anyone can give.

Upvotes: 1

Views: 1181

Answers (1)

dkozl
dkozl

Reputation: 33364

You're binding to a static property via Path and that won't work. Change Binding to x:Static and should work

<MenuItem Name="mnCopy" Command="ApplicationCommands.Copy" />      
<MenuItem Name="mnDuplicate" Command="{x:Static classes:myCommands.Duplicate}"/>

On a side note RoutedUICommand has overloaded constructor that accepts InputGestureCollection where you can bind Ctrl+D when you command is created.

private static readonly RoutedUICommand _duplicateCmd = 
    new RoutedUICommand(
           "Duplicate", 
           "Duplicate", 
           typeof(myCommands), 
           new InputGestureCollection(new InputGesture[] { new KeyGesture(Key.D, ModifierKeys.Control) }));

advantage is that you won't have to specify InputGestureText, as you don't have to ApplicationCommands.Copy, and because you use RoutedUICommand you also don't need to specify Header. If you do that both InputGestureText and Header will be taken by default from your RoutedUICommand and all you actually need to specify against MenuItem is a Command

Upvotes: 2

Related Questions