caesay caesay - 3 years ago 315
C# Question

WPF KeyBinding swallowing keys, preventing TextBox use

Problem Overview:


's defined at a level higher than a
(with no modifier keys assigned), prevents the user from typing those keys inside the

Minimal XAML Hierarchy:


Minimal Command/KeyBinding:

<RoutedUICommand x:Key="Commands.SomeCommand" />
<KeyBinding Key="A" Command="{StaticResource Commands.SomeCommand} />
<CommandBinding Command="{StaticResource Commands.SomeCommand}" Executed="..." />

, are defined at the first
level. So in this example, in the textbox, the user can type freely until they press the
key, and then it just does not insert the letter into the textbox. I can clearly see that the
are firing when you press the
key (and
Handled = false
) , but the letter will not get added to the text of the textbox and
does not fire.

I'm looking for any suggestions that may indicate what is swallowing the keypress and stopping it from getting processed by the TextBox, or anything related to how I can debug this issue.

Thanks to Snoop, I was able to clearly see the problem.

  1. TextBox.PreviewKeyDown
    tunnels down and fires through the visual tree, starting at the Window, and ending at the TextBox

  2. TextBox.KeyDown
    bubbles back up starting at the TextBox and heading towards the window

  3. TextBox.KeyDown
    gets Handled set to true by the first UserControl that has the KeyBinding set.

  4. TextBox.PreviewTextInput
    never fires, nor does the textbox process the input, because the KeyDown event was set as handled.

This still leaves the problem, how do you prevent the UserControl from handling the input if a textbox has focus? Within the Command execution, I can check if a textbox has keyboard focus, but by this time it's too late.

Answer Source

TextInput and PreviewTextInput only fires when the Text actually changes / might change.

As you updated your question to reflect, the Command intercepts the event and the (Preview)TextInput events are never raised.

The nicest solution would be to add a modifier key to your KeyBinding, but I suspect that is not your preferred way to go.

Another option would be to e.Handle the PreviewKeyDown event on the TextBox and raise the TextComposition events yourself, using something like:

target.RaiseEvent(new TextCompositionEventArgs(InputManager.Current.PrimaryKeyboardDevice, 
new TextComposition(InputManager.Current, target, "A")) 
    RoutedEvent = TextCompositionManager.TextInputEvent 

(Alternatively, insert into textBox.Text at the correct CaretIndex)

Truth be told, it would still be a hack.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download