Да, привязки клавиш - это боль. И я согласен с Рэйчел в том, что в этом конкретном случае вы, вероятно, хотите что-то доступное на уровне окна.
Вы можете избежать кода и получить доброту mvvm, выполнив следующие действия:
- информируйте ваши команды о жестах клавиш
- дает связыванию ключей дополнительное свойство, которое использует (1)
Это, очевидно, небольшая инфраструктурная работа, так как она может быть проверена и повторно использована, когда она у вас есть. В этом случае, так как вы хотите, чтобы привязки были доступны на уровне окна, ваш ShellVm содержит команды и делегаты для дочерних моделей представления по мере необходимости. Я оставил достаточно кода, чтобы дать вам представление о идее
НТН,
Berryl
пример привязок
<Window.InputBindings>
<cmdRef:KeyBindingEx CommandReference="{Binding AddCommand}"/>
</Window.InputBindings>
расширенная привязка клавиш
public class KeyBindingEx : KeyBinding
{
public static readonly DependencyProperty CommandReferenceProperty = DependencyProperty
.Register("CommandReference", typeof(CommandReference), typeof(KeyBindingEx),
new PropertyMetadata(OnCommandReferenceChanged));
private static void OnCommandReferenceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var kb = (KeyBinding) d;
var cmdRef = e.NewValue as VmCommand;
if(cmdRef==null) return;
kb.Key = cmdRef.GestureKey;
kb.Modifiers = cmdRef.GestureModifier;
kb.Command = cmdRef;
}
public CommandReference CommandReference
{
get { return (CommandReference)GetValue(CommandReferenceProperty); }
set { SetValue(CommandReferenceProperty, value); }
}
}
Справочник команд, извлечение базового класса
открытый класс CommandReference: PropertyChangedBase
{
...
public Key GestureKey
{
get { return _gestureKey; }
set
{
if (_gestureKey == value) return;
_gestureKey = value;
NotifyOfPropertyChange(() => GestureKey);
}
}
private Key _gestureKey;
}
/// <summary>A command whose primary purpose is to relay its functionality to other objects by invoking delegates.</summary>
public class VmCommand : CommandReference, ICommand
{
...
/// <summary>Action to be called when the Execute method of the command gets called</summary>
public Action ExecuteDelegate { get; protected set; }
/// <summary>Predicate to execute when the CanExecute of the command gets called (default is <c>true</c>)</summary>
public Func<bool> CanExecuteDelegate { get; protected set; }
}