In WPF (XAML/C#), I can bind a hotkey on the window to execute a command, like:
<Window.InputBindings>
<KeyBinding Modifier="Control" Key="Space" Command="{Binding TogglePushToTalk}"/>
</Window.InputBindings>
This executes the ICommand
called TogglePushToTalk
in my ViewModel when Ctrl+Space is pressed then subsequently released.
Is there a way to bind commands or actions to the press and release events individually, in an MVVM-friendly way, without getting into code-behind? I.e., so that pressing Ctrl+Space will execute StartPushToTalk
, and then releasing those keys will call StopPushToTalk
.
Is there a way to bind commands or actions to the press and release events individually, in an MVVM-friendly way, without getting into code-behind?
Not using pure XAML but you could implement an attached behaviour. Here is an example that should at least give you the idea:
public static class KeyBehavior
{
public static readonly DependencyProperty KeyDownCommandProperty = DependencyProperty.RegisterAttached(
"KeyDownCommand", typeof(ICommand), typeof(KeyBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSet)));
public static readonly DependencyProperty KeyUpCommandProperty = DependencyProperty.RegisterAttached(
"KeyUpCommand", typeof(ICommand), typeof(KeyBehavior));
private static void OnSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Window w = (Window)d;
w.KeyDown += OnKeyDown;
}
private static void OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
Window w = (Window)sender;
ICommand keyDownCommand = GetKeyDownCommand(w);
if (keyDownCommand != null)
{
w.KeyUp += W_KeyUp;
keyDownCommand.Execute(null);
}
}
}
private static void W_KeyUp(object sender, KeyEventArgs e)
{
Window w = (Window)sender;
w.KeyUp -= W_KeyUp;
ICommand keyUpCommand = GetKeyUpCommand(w);
if (keyUpCommand != null)
keyUpCommand.Execute(null);
}
public static void SetKeyDownCommand(Window element, ICommand value) => element.SetValue(KeyDownCommandProperty, value);
public static ICommand GetKeyDownCommand(Window element) => (ICommand)element.GetValue(KeyDownCommandProperty);
public static void SetKeyUpCommand(Window element, ICommand value) => element.SetValue(KeyUpCommandProperty, value);
public static ICommand GetKeyUpCommand(Window element) => (ICommand)element.GetValue(KeyUpCommandProperty);
}
You may want to add dependency properties for the keys in order to be able to reuse the command for several different keys and key combinations.