Reputation: 4571
Untill now, I'm using the .xaml.cs to handle the inputs.
Here is my xaml head code :
<Window x:Class="My_Windows_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:My_Windows_App.ViewModel"
Title="MainWindow" Height="600" Width="900"
Keyboard.KeyDown="keyDownEventHandler" Keyboard.KeyUp="keyUpEventHandler">
And here is a part of the MainWindow.xaml.cs code :
public partial class MainWindow : Window
{
private bool pushToTalk;
public void keyDownEventHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl)
pushToTalk = true;
}
public void keyUpEventHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl)
pushToTalk = false;
}
}
How can I implent the same thing in MVVM ? Because as far as I understand, we can not bind a method, only properties, right ?
Upvotes: 9
Views: 19257
Reputation: 790
The following works for handling the "Enter" key in a TextBox:
<TextBox Text="{Binding UploadNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding
Key="Enter"
Command="{Binding FindUploadCommand}"
CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
</TextBox.InputBindings>
Upvotes: 2
Reputation: 11783
Seems you got your answer, but here's another take on a solution.
You can tackle the keyboard events with i:interaction
and InputBindings
. Some examples using a DatePicker
with interaction would be:
<DatePicker Name="fancy_name_here" SelectedDate="{Binding your_date_property_here}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<i:InvokeCommandAction Command="{Binding Path=TestMeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DatePicker>
(Do note that you'll need the next line in your window definitions for the i:Interaction
to work:)
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
and for the input binding:
<DatePicker Name="fancy_name_here" SelectedDate="{Binding your_date_property_here}">
<DatePicker.InputBindings>
<KeyBinding Key="Up" Modifiers="Shift" Command="{Binding your_command_name}" />
<KeyBinding Key="Up" Modifiers="Alt" Command="{Binding TestMeCommand}" />
<KeyBinding Key="Up" Command="{Binding TestMeCommand}" />
</DatePicker.InputBindings>
</DatePicker>
Feel free to have a look at my other answer , it discusses i:interaction
and InputBindings
, and points in return to another article about handling key events: up/down on datepicker, and discusses the code behind / mvvm approaches.
Hope you'll find them useful.
Upvotes: 22
Reputation: 44068
Input handling is a View concern, not a ViewModel concern, why would you want to move that to the ViewModel?
instead, delegate the application / business logic to the ViewModel, while keeping the Keyboard Input handling in the View:
public partial class MainWindow : Window
{
private MyViewModel ViewModel;
public MainWindow()
{
ViewModel = new MyViewModel();
}
public void keyDownEventHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl)
ViewModel.PushToTalk = true;
}
public void keyUpEventHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl)
ViewModel.PushToTalk = false;
}
}
Notice how I moved the PushToTalk
property to the ViewModel, because that is really part of the application logic and not the UI, while keeping Keyboard events at the View level. This does not break MVVM because you're not mixing UI and application logic, you're just placing things where they really belong.
Upvotes: 7