问题
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?
回答1:
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);
}
}
来源:https://stackoverflow.com/questions/3364919/can-i-use-caliburn-to-bind-to-routedcommands