WPF where are key bindings stored?

deleyd
deleyd used Ask the Experts™
on
In a WPF application, say I have a window, and I set up a key binding to run a command if I press a certain key on the keyboard.

Somewhere in my Window object I expect my key binding is stored. I expect when a key is pressed on the keyboard, that generates a "key was pressed" event, and the operating system determines which window has focus, (and perhaps what control on the window has focus,) and sends the "key was pressed" event to to window, and the window has a list of events it handles, and if there's a match then it calls the corresponding event handler.

But I can't find that list.

Maybe it doesn't work that way. Maybe the window registers the events it's interested in with some higher power, and that higher power keeps the list of events the window handles.

Either way, my problem is I press the key, and... nothing happens.

So I'm trying to trace what happens to this key event, because it's not resulting in my command being called.

Also, is there a list of keyboard key names that can be used in WPF XAML files? I've seen the list of Key Enumerations at https://msdn.microsoft.com/en-us/library/system.windows.input.key(v=vs.110).aspx. It lists "OemPlus" for the keyboard "+" key; however, I've seen XAML code that uses
key="Plus"

Open in new window

, which seems to work, but I don't see that documented anywhere.

So my questions are:

1. Is there documentation for what key names can be used in a WPF XAML file for the "Key="<string>"

2. Is there a way to trace what happens to a keyboard key pressed event when what I'm expecting to happen doesn't happen?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Software Engineer
Commented:
I found the answer I was looking for. It's in the source code for System.Windows.Input.KeyConverter.cs There the code is:
        private object GetKey(string keyToken, CultureInfo culture)
        { 
            if (keyToken == String.Empty)
            {
                return Key.None;
            } 
            else
            { 
                keyToken = keyToken.ToUpper(culture); 
                if (keyToken.Length == 1 && Char.IsLetterOrDigit(keyToken[0]))
                { 
                    if (Char.IsDigit(keyToken[0]) && (keyToken[0] >= '0' && keyToken[0] <= '9'))
                    {
                        return ((int)(Key)(Key.D0 + keyToken[0] - '0'));
                    } 
                    else if (Char.IsLetter(keyToken[0]) && (keyToken[0] >= 'A' && keyToken[0] <= 'Z'))
                    { 
                        return ((int)(Key)(Key.A + keyToken[0] - 'A')); 
                    }
                    else
                    {
                        throw new ArgumentException(SR.Get(SRID.CannotConvertStringToType, keyToken, typeof(Key)));
                    }
                } 
                else
                { 
                    Key keyFound = (Key)(-1); 
                    switch (keyToken)
                    { 
                        case "ENTER": keyFound = Key.Return; break;
                        case "ESC": keyFound = Key.Escape; break;
                        case "PGUP": keyFound = Key.PageUp; break;
                        case "PGDN": keyFound = Key.PageDown; break; 
                        case "PRTSC": keyFound = Key.PrintScreen; break;
                        case "INS": keyFound = Key.Insert; break; 
                        case "DEL": keyFound = Key.Delete; break; 
                        case "WINDOWS": keyFound = Key.LWin; break;
                        case "WIN": keyFound = Key.LWin; break; 
                        case "LEFTWINDOWS": keyFound = Key.LWin; break;
                        case "RIGHTWINDOWS": keyFound = Key.RWin; break;
                        case "APPS": keyFound = Key.Apps; break;
                        case "APPLICATION": keyFound = Key.Apps; break; 
                        case "BREAK": keyFound = Key.Cancel; break;
                        case "BACKSPACE": keyFound = Key.Back; break; 
                        case "BKSP": keyFound = Key.Back; break; 
                        case "BS": keyFound = Key.Back; break;
                        case "SHIFT": keyFound = Key.LeftShift; break; 
                        case "LEFTSHIFT": keyFound = Key.LeftShift; break;
                        case "RIGHTSHIFT": keyFound = Key.RightShift; break;
                        case "CONTROL": keyFound = Key.LeftCtrl; break;
                        case "CTRL": keyFound = Key.LeftCtrl; break; 
                        case "LEFTCTRL": keyFound = Key.LeftCtrl; break;
                        case "RIGHTCTRL": keyFound = Key.RightCtrl; break; 
                        case "ALT": keyFound = Key.LeftAlt; break; 
                        case "LEFTALT": keyFound = Key.LeftAlt; break;
                        case "RIGHTALT": keyFound = Key.RightAlt; break; 
                        case "SEMICOLON": keyFound = Key.OemSemicolon; break;
                        case "PLUS": keyFound = Key.OemPlus; break;
                        case "COMMA": keyFound = Key.OemComma; break;
                        case "MINUS": keyFound = Key.OemMinus; break; 
                        case "PERIOD": keyFound = Key.OemPeriod; break;
                        case "QUESTION": keyFound = Key.OemQuestion; break; 
                        case "TILDE": keyFound = Key.OemTilde; break; 
                        case "OPENBRACKETS": keyFound = Key.OemOpenBrackets; break;
                        case "PIPE": keyFound = Key.OemPipe; break; 
                        case "CLOSEBRACKETS": keyFound = Key.OemCloseBrackets; break;
                        case "QUOTES": keyFound = Key.OemQuotes; break;
                        case "BACKSLASH": keyFound = Key.OemBackslash; break;
                        case "FINISH": keyFound = Key.OemFinish; break; 
                        case "ATTN": keyFound = Key.Attn; break;
                        case "CRSEL": keyFound = Key.CrSel; break; 
                        case "EXSEL": keyFound = Key.ExSel; break; 
                        case "ERASEEOF": keyFound = Key.EraseEof; break;
                        case "PLAY": keyFound = Key.Play; break; 
                        case "ZOOM": keyFound = Key.Zoom; break;
                        case "PA1": keyFound = Key.Pa1; break;
                        default: keyFound = (Key)Enum.Parse(typeof(Key), keyToken, true); break;
                    } 
 
                    if ((int)keyFound != -1) 
                    { 
                        return keyFound;
                    } 
                    return null;
                }
            }
        } 

Open in new window

There's where "Plus" gets converted to Key.OemPlus. And if the string case statement doesn't match anything, then Enum.Parse is used to convert "OemPlus" to Key.OemPlus.

And I finally did find the list of key bindings, though it's buried deep:
Key Binding for OemMinus key (part 1)Key Binding for OemMinus key (part 2)
(I'm still not sure if there's a way to debug what happens to a keyboard key event if nothing happens and I'm expecting something to happen. The event might be handled somewhere else before it gets to where I expect it to go.)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial