Search code examples
c#wpfmvvmprism-6

How to handle a key press event in ViewModel using Prism 6 in WPF?


I have a situation where I need to handle a keypress event, it can be any from A-Z, 0-9 but I need to handle that in ViewModel. WHich key is pressed should be passed nito the ViewModel. I am using prism 6.0 so the View1ViewModel is Auto-wired with the view1.

I know that for specific keys I can handle but how to do the same for all keys.

I have a property in ViewModel "KeyPressed", and I tried the below code in code-behind

private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
{
    _mainWindowViewModel.KeyPressed = e.Key;
}

But this code doesn't update the View1ViewModel as in Prism framework viewmodel and view binding is through the framework. I have tried to use interaction, I put the below code in the root Grid section.

<i:Interaction.Triggers >
   <i:EventTrigger EventName="KeyUp">
      <i:InvokeCommandAction Command="{Binding KeyUpEventCommand}" 
        CommandParameter="..."/>
    </i:EventTrigger>
</i:Interaction.Triggers>

The event gets fired but as there is no Command parameter so its null. I need to pass a commandParameter, but don't know what it should be!

In ViewModel:

public DelegateCommand KeyUpEventCommand { get; private set; }

private string strAlphabet;
public string Alphabets
{
     get { return strAlphabet; }
     set { SetProperty(ref strAlphabet, value); }
}

public MainWindowViewModel(IEventAggregator eventAggregator)
{
     KeyUpEventCommand = new DelegateCommand(KeyUpEventHandler);
}

public void KeyUpEventHandler()
{
     //This logic can be changed
     if (Alphabets == "A")
     {
         // Perform some action
     }
     if (Alphabets == "B")
     {
         // Perform some other action
     }
}

Any ideas/suggestions how can I handle this?


Solution

  • The type of the command property should be DelegateCommand<KeyEventArgs>:

    public DelegateCommand<KeyEventArgs> KeyUpEventCommand { get; private set; }
    
    private string strAlphabet;
    public string Alphabets
    {
        get { return strAlphabet; }
        set { SetProperty(ref strAlphabet, value); }
    }
    
    public MainWindowViewModel(IEventAggregator eventAggregator)
    {
        KeyUpEventCommand = new DelegateCommand<KeyEventArgs>(KeyUpEventHandler);
    }
    
    public void KeyUpEventHandler(KeyEventArgs args)
    {
        //...
    }
    

    Also make sure that you are using the Prism's own InvokeCommandAction class and don't set the CommandParameter property of it:

    xmlns:prism="http://prismlibrary.com/"
    ...
    <i:Interaction.Triggers >
        <i:EventTrigger EventName="PreviewKeyDown">
            <prism:InvokeCommandAction Command="{Binding KeyUpEventCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    

    Then the KeyEventArgs should be passed as a command parameter by default.