dr11
dr11

Reputation: 5756

Create Key binding in WPF

I need to create input binding for Window.

public class MainWindow : Window
{
    public MainWindow()
    {
        SomeCommand = ??? () => OnAction();
    }

    public ICommand SomeCommand { get; private set; }

    public void OnAction()
    {
        SomeControl.DoSomething();
    }
}

<Window>
    <Window.InputBindings>
        <KeyBinding Command="{Binding SomeCommand}" Key="F5"></KeyBinding>
    </Window.InputBindings>
</Window>

If I init SomeCommand with some CustomCommand : ICommand it doesn't fire. SomeCommand property getter is never called.

Upvotes: 35

Views: 81765

Answers (5)

Mike Nakis
Mike Nakis

Reputation: 62129

Normally, a command is not supposed to live in a view; it is supposed to live in a viewmodel. However, on some rare occasions it might make sense to have a command in a view. On such occasions, it is indeed unclear how to connect the key-binding to the command, as the OP found out.

This is how I solved this problem in my project:

<Window x:Class="MyNamespace.MyView"
    (...)
    xmlns:local="clr-namespace:MyNameSpace"
    (...)
    <Grid>
        <Grid.InputBindings>
            <KeyBinding Key="R" Command="{Binding ReportCommand, 
                RelativeSource={RelativeSource AncestorType=local:MyView}}" />
    (...)

ReportCommand is an ICommand in MyView, not in the ViewModel.

Upvotes: 2

Aleksey
Aleksey

Reputation: 1347

For your case best way used MVVM pattern

XAML:

<Window>
    <Window.InputBindings>
        <KeyBinding Command="{Binding SomeCommand}" Key="F5"/>
    </Window.InputBindings>
</Window>

Code behind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

In your view-model:

public class MyViewModel
{
    private ICommand someCommand;
    public ICommand SomeCommand
    {
        get
        {
            return someCommand 
                ?? (someCommand = new ActionCommand(() =>
                {
                    MessageBox.Show("SomeCommand");
                }));
        }
    }
}

Then you'll need an implementation of ICommand. This simple helpful class.

public class ActionCommand : ICommand
{
    private readonly Action _action;

    public ActionCommand(Action action)
    {
        _action = action;
    }

    public void Execute(object parameter)
    {
        _action();
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;
}   

Upvotes: 78

Jitendra Pancholi
Jitendra Pancholi

Reputation: 7562

It might be too late but here is the simplest and shortest solution.

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.S)
    {
         // Call your method here
    }
}

<Window x:Class="Test.MainWindow" KeyDown="Window_KeyDown" >

Upvotes: 7

Paul-Sebastian Manole
Paul-Sebastian Manole

Reputation: 2700

For modifiers (key combinations):

<KeyBinding Command="{Binding SaveCommand}" Modifiers="Control" Key="S"/>

Upvotes: 20

Nitin Purohit
Nitin Purohit

Reputation: 18578

You will have to create your own Command implementing ICommand interface and initialize SomeCommand with the instance of that Command.

Now you have to set the DataContext of Window to self in order to make the Command Binding work:

public MainWindow()
{
    InitializeComponents();
    DataContext = this;
    SomeCommand = MyCommand() => OnAction();
}

OR you will have to update your Binding as

 <Window>
   <Window.InputBindings>
    <KeyBinding Command="{Binding SomeCommand, RelativeSource={RelativeSource Self}}" Key="F5"></KeyBinding>
   </Window.InputBindings>
 </Window>

Upvotes: 2

Related Questions