Create Key Binding in Wpf

Create Key binding in WPF

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;
}

WPF Input Key Binding

check the proper key binding below
Link : WPFKeyBindings

Basic Keys

Key - Code Key(s)

A - Z The basic letter keys.

D0 - D9 The numeric keys from the main section of the keyboard.
Space The space bar.

F1 - F24 The function keys.

How do I create a XAML KeyBinding for CTRL+'

An apostrophe is not a key. It's a character that is eventually mapped to a key depending on the input device. OemQuestion works on my keyboard:

<KeyBinding Modifiers="CTRL" Key="OemQuestion"  Command="{Binding MyCommand}"/>

...but you may be better off handling the PreviewTextInput event if you really want to detect when an apostrophe is typed in:

How to detect when (forward) slash key is pressed in OEM keys C#

Create a simple, unmodified key binding in WPF (.net core 3.1 /.net 5)

NotSupportedException: Die Kombination aus Taste und Modifizierer "None+H" wird für KeyGesture nicht unterstützt.

Both of your solutions work for .NET Framework, as well as .NET Core 3.1. This exception is clearly about KeyGesture. You instantiate a KeyGesture with a None modifier like below when creating the key binding and that will throw the NotSupportedException. Removing this line or assigning a modifier will resolve it.

InputBindings.Add(new KeyBinding(MyRoutedCommand, Key.H, ModifierKeys.None));

As a reference from MSDN about KeyGesture and modifier keys:

In most cases, a KeyGesture must be associated with one or more ModifierKeys. The exceptions to this rule are the function keys and the numeric keypad keys, which can be a valid KeyGesture by themselves.

C# WPF add KeyBinding events in XAML

This line can't work:

<KeyBinding Modifiers="Ctrl" Key="LeftCtrl" Command="{Binding _listener_OnKeyPressed}"/>

KeyBinding.Command expects an object implementing ICommand, you are binding it to a method.

A basic implementation of the ICommand interface would look something like this:

class SimpleCommand : ICommand
{
public event EventHandler<object> Executed;

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

public void Execute(object parameter)
{
if (Executed != null)
Executed(this, parameter);
}

public event EventHandler CanExecuteChanged;
}

Which you could use like this:

<Window.InputBindings>
<KeyBinding Modifiers="Control" Key="Add">
<KeyBinding.Command>
<local:SimpleCommand Executed="SimpleCommand_OnExecuted"/>
</KeyBinding.Command>
</KeyBinding>
</Window.InputBindings>

And in code behind:

private void SimpleCommand_OnExecuted(object sender, object e)
{
MessageBox.Show("SimpleCommand Executed");
}

Usually you would use Commanding to define the Command in code and use it in XAML. When you bind that Command to a KeyBinding, Button or MenuItem (or something else), the CanExecute method of your implementation can be used to disable the command (and therefore disabling the Element it's bound to).

Creating KeyBinding in WPF with more than one modifier key

The documentation states that you can just separate the modifiers with the + character:

<KeyBinding Modifiers="Ctrl+Shift" Key="S" Command="{Binding SaveCommand}" />

See here for the gory details, with the relevant bits extracted below in case the link ever disappears:


XAML

<object property="oneOrMoreModifierKeys"/>

XAML Values

oneOrMoreModifierKeys — One or more modifier keys, defined by the ModifierKeys enumeration, delimited with a + character.


You can also use a gesture on its own rather than a key/modifier combo:

<KeyBinding Gesture="Ctrl+Shift+S" Command="{Binding SaveCommand}" />

as per that same documentation link:

When defining a KeyBinding in XAML, there are two ways to specify the KeyGesture.

The first way to establish a KeyBinding in XAML is to define the Gesture attribute of the KeyBinding element, which enables a syntax to specify keys and modifiers as a single string, for example "CTRL+P".

The second way is to define the Key attribute and the Modifiers attributes of the KeyBinding element.

Both ways of setting the KeyGesture are equivalent and modify the same underlying object, but there will be a conflict if both are used. In the case when the Key, Modifiers, and the Gesture attributes are all set, the attribute which is defined last will be used for the KeyGesture.

Problems with WPF command key bindings

This worked on the first try for me (at least up until SaveFileDialog threw an exception about the filter string). I put the KeyBinding in Window.InputBindings and the CommandBinding in Window.CommandBindings.

<Window 
x:Class="Test3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test3"
xmlns:commands="clr-namespace:Commands"
Title="MainWindow"
Height="350"
Width="525">
<Window.InputBindings>
<KeyBinding Command="local:customCommands.saveFile" Key="S" Modifiers="Ctrl"/>
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="local:customCommands.saveFile" Executed="launchSaveDialog"/>
</Window.CommandBindings>
<Grid>
<RichTextBox x:Name="RTB" />
</Grid>
</Window>

I defined customCommands as follows:

public static class customCommands
{
static customCommands()
{
saveFile = new RoutedCommand("saveFile", typeof(MainWindow));
}
public static RoutedCommand saveFile { get; private set; }
}

I got an exception about the filter string, due to the trailing pipe character. It seems to regard that as a separator, not a terminator:

Provided filter string is not valid. Filter string should contain a description of the filter, followed by a vertical bar and the filter pattern. Must also separate multiple filter description and pattern pairs by a vertical bar. Must separate multiple extensions in a filter pattern with a semicolon. Example: "Image files (*.bmp, .jpg)|.bmp;.jpg|All files (.)|.*"

Easy fix:

private void launchSaveDialog(object sender, ExecutedRoutedEventArgs e)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "Rich Text format (*.rtf)|*.rtf";
dlg.DefaultExt = ".rtf";
dlg.OverwritePrompt = true;
if (dlg.ShowDialog() == true)
{
FileStream fileStream = new FileStream(dlg.FileName, FileMode.Create);
TextRange range = new TextRange(RTB.Document.ContentStart, RTB.Document.ContentEnd);
range.Save(fileStream, DataFormats.Rtf);
}
}

It's possible that you're eating keyboard input somewhere, but you didn't show that code so I'm just throwing it out there.

The insistence on javaCase names is relatively harmless but it does little for readability.

How do I create a keybinding to the backslash key in WPF?

EDIT

I highly suggest you to refrain yourself from scrolling down to the end of the edit, I know the keyboard picture is very tempting but read everything in order for a better experience :D

As I said, there is no point in absolutely trying, this method is unreliable so how can you expect something unreliable to work reliably ? There is absolutely no point in even trying to reverse-engineer a driver or decipher USB streams just for that, anyone sane would tell you this :D

Even you'd achieve any of these (which IMO is highly unsure), you'd have it done for a particular brand of keyboard. The other thing is the time factor, it's a huge waste of time for the outcome.

The closest thing to metal in C# I've found is this :

Using Raw Input from C# to handle multiple keyboards

RawInputProcess.RawKeyboard.ProcessRawInput calls GetRawInputData from User32
And even this low-level stuff does return 0xDC or 220 (i.e. the terrific Oem5). This calls VirtualKeyCorrection which corrects some keys, you could do something there though it's pretty ugly as well and as unreliable as it can be.

Additionally, there's a bunch of links about HID libraries here

My definitive answer :

You absolutely want to be able to bind ?

  • Create a form that allows the user to define shortcuts
  • Do the ugly hack I've shown with the StackOverflow :D
  • Make the default shortcut for this command to use Oem5
  • Pray that no violent psychopath knocks at your door

And there you will have your default binding to Ctrl+\.

Now a bit of history and something you probably haven't caught yet !

If you closely look at the MSDN docs -> Keys Enumeration

OemBackslash

The OEM angle bracket or backslash key on the RT 102 key keyboard (Windows 2000 or later).

I'm pretty sure you know this thing but did not even pay attention to it.

enter image description here

enter image description here

I've personally been playing with it on an IBM XT clone back in '86 when I was 5.

Now you're probably starting to understand but I'll just make it crystal clear :

The OemBackslash is a vestige from the 80's pretty much like many other things in Windows (though most if not all have been removed in current versions)

So unless you do have one of these keyboards, you will never receive this KeyCode !

I cannot be 100% certain unless someone tests the RT-102 with a DIN to PS/2 adapter under 2000/XP, it'd be interesting to see the result; but what makes me confident in saying this is, 1st the docs, 2nd generally people at Microsoft know what they do, they wrote that thing. I would eat my hat if this came to be false.

I hope you will be satisfied with my edit and finally mourn OemBackslash, I perfectly understand your desire of seeing such thing on your screen but nothing is perfect, especially in computing. I gave you a pseudo workaround which is literally equivalent, give it a try !

Credits for the pictures goes to :

  • http://deskthority.net/wiki/NMB_RT-100/RT-8200_series
  • http://geekhack.org/index.php?topic=12861.0

I've been reading your previous question, I'd tell you as Hans said: not a good idea to bind to it because it won't necessarily be a backslash.

For example in the French keyboard to get the backslash you have to press AltGr and 8, AltGris nothing more than Alt+Ctrl which implies additionally pressing Alt for this layout to execute your command.

http://en.wikipedia.org/wiki/AltGr_key

In short this shortcut is unreliable as it is not constant according layout and/or manufacturer.

In WPF there is KeyInterop.VirtualKeyFromKey but it returns Oem5 as well :(

Looking at the docs give the definitive answer : Virtual-Key Codes

VK_OEM_5
0xDC
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '\|' key

But here's a solution :D

Hitting \ will bring Oem5 but by sending an event to a TextBox for instance your system will do all the magic to transform it to a \. You can then grab the TextBox.Text and act accordingly depending the key that's been typed along with the modifiers.

enter image description here

private bool _done;
private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
{
if (_done) return;
_done = true;

var presentationSource = PresentationSource.FromDependencyObject(this);
var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, presentationSource, 0, e.Key)
{
RoutedEvent = KeyDownEvent
};
TextBox1.Focus();
TextBox1.RaiseEvent(keyEventArgs);
}

private void TextBox1_OnTextChanged(object sender, TextChangedEventArgs e)
{
var text = TextBox1.Text;
}

NOTE 1 : the boolean is here to prevent a StackOverflow :D

NOTE 2 : this is probably as unreliable as the key is, what if the user has Shift on ? I didn't try

This is just a proof on concept that it is possible but personally I would not take this path, it's too ugly IMO; I'd rather allow the user to map commands to whatever gesture he wishes. And obviously not allow him to bind to \ :)

EDIT

I have an MS keyboard and there is mskey.exe that allows to diagnose your keyboard :

enter image description here

It does import HID.DLL functions such as HidP_GetValueCaps so you might be able to achieve this in a cleaner manner through some P/Invoke but it seems a lot of work though.



Related Topics



Leave a reply



Submit