wpfrouted-commandscaliburn

Can I use Caliburn to bind to RoutedCommands?


What's the best way to use WPF's built-in RoutedCommands with Caliburn?

For example, in my shell I have an Edit menu with a Copy item in it attached to the standard command found in ApplicationCommands:

<Menu>
    <MenuItem Header="Edit">
        <MenuItem Header="Copy"
                  Command="ApplicationCommands.Copy" />
    </MenuItem>
</Menu>

I want this item to be handled by a TextBox when it has the focus and by my own controls when they have the focus. In my controls I can handle Execute and CanExecute in code behind by creating a CommandBinding:

<UserControl.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Copy"
                    Executed="CopyCommandExecute"
                    CanExecute="CanCopyCommandExecute" />
</UserControl.CommandBindings>

Is there a way, using Caliburn, to handle with methods in my ViewModel instead, or to redirect to another command that I expose from the ViewModel? Or am I going about this the wrong way?


Solution

  • I ended up creating a behaviour that allows the clipboard RoutedCommands to be redirected to other commands.

    public class ClipboardBehavior : Behavior<Control>
    {
        public static readonly DependencyProperty CopyCommandProperty =
            DependencyProperty.Register("CopyCommand",
                                        typeof (ICommand),
                                        typeof (ClipboardBehavior),
                                        new PropertyMetadata(default(ICommand)));
    
        public static readonly DependencyProperty CutCommandProperty =
            DependencyProperty.Register("CutCommand",
                                        typeof (ICommand),
                                        typeof (ClipboardBehavior),
                                        new PropertyMetadata(default(ICommand)));
    
        public static readonly DependencyProperty DeleteCommandProperty =
            DependencyProperty.Register("DeleteCommand",
                                        typeof (ICommand),
                                        typeof (ClipboardBehavior),
                                        new PropertyMetadata(default(ICommand)));
    
        public static readonly DependencyProperty PasteCommandProperty =
            DependencyProperty.Register("PasteCommand",
                                        typeof (ICommand),
                                        typeof (ClipboardBehavior),
                                        new PropertyMetadata(default(ICommand)));
    
        public ICommand DeleteCommand
        {
            get { return (ICommand) GetValue(DeleteCommandProperty); }
            set { SetValue(DeleteCommandProperty, value); }
        }
    
        public ICommand CutCommand
        {
            get { return (ICommand) GetValue(CutCommandProperty); }
            set { SetValue(CutCommandProperty, value); }
        }
    
        public ICommand CopyCommand
        {
            get { return (ICommand) GetValue(CopyCommandProperty); }
            set { SetValue(CopyCommandProperty, value); }
        }
    
        public ICommand PasteCommand
        {
            get { return (ICommand) GetValue(PasteCommandProperty); }
            set { SetValue(PasteCommandProperty, value); }
        }
    
        protected override void OnAttached()
        {
            AddBinding(ApplicationCommands.Delete, () => DeleteCommand);
            AddBinding(ApplicationCommands.Cut, () => CutCommand);
            AddBinding(ApplicationCommands.Copy, () => CopyCommand);
            AddBinding(ApplicationCommands.Paste, () => PasteCommand);
        }
    
        private void AddBinding(ICommand command, Func<ICommand> executingCommand)
        {
            var binding = new CommandBinding(command,
                                             (sender, e) => Execute(e, executingCommand()),
                                             (sender, e) => CanExecute(e, executingCommand()));
    
            AssociatedObject.CommandBindings.Add(binding);
        }
    
        private static void CanExecute(CanExecuteRoutedEventArgs args, ICommand command)
        {
            if (command != null)
            {
                args.CanExecute = command.CanExecute(args.Parameter);
                args.ContinueRouting = false;
            }
        }
    
        private static void Execute(ExecutedRoutedEventArgs e, ICommand command)
        {
            if (command != null)
                command.Execute(e.Parameter);
        }
    }