Elfayer
Elfayer

Reputation: 4571

C# - How to handle XAML Keyboard in MVVM?

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

Answers (3)

Keith Davidson
Keith Davidson

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

Noctis
Noctis

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

Fede
Fede

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

Related Questions