WPF where are key bindings stored?

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

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?
deleydSoftware EngineerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

deleydSoftware EngineerAuthor 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;
                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')); 
                        throw new ArgumentException(SR.Get(SRID.CannotConvertStringToType, keyToken, typeof(Key)));
                    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.)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.