http://blogs.clariusconsulting.net/kzu

Daniel Cazzulino's Blog

Go Back to
kzu′s Latest post

NavigationWindow, WinFormsHost and TextBoxes: backspace bug

WPF NavigationWindow is a very handy class that allows you to easily build Vista-like wizards, or any kind of window that resembles the browser-style navigation:


NavWindow
  

The NavigationWindow will automatically handle the Backspace, Back/Next keys and perform the appropriate navigation on the window pages.

If you’re combining this class with the WindowsFormsHost to integrate WinForms controls, you may hit a very annoying bug: if there are textboxes in your WinForm control, hitting Backspace while editing the input on it will cause the navigation window to navigate back, instead of deleting the text on the TextBox. Yikes!

Being WPF the new kid on the block, I was immediately tempted to blame it. Turns out it’s a bug in the WinForms TextBoxBase :S.

You see, before WPF gets a chance to handle an input message, WindowsFormsHost tries to determine whether any contained control is interested in handling the message first and gives it the option to do that right away. This is done by calling the WinForms Control.PreProcessControlMessage() which ultimately calls the virtual Control.IsInputKey which controls use to determine a particular key is part of their input processing. The problem is that TextBoxBase does not say it’s interested in handling the Backspace key (but it does so for Esc, Tab, Home, End, etc., and inherits the text keys from the base Control class implementation of IsInputKey).

Therefore, the WindowsFormsHost doesn’t do anything further with the message, and the message enters the WPF input system, where it induces events tunneled and bubbled across the element tree. Eventually, NavigationWindow handles the key thanks to the built-in CommandBinding for navigating back. Bummer :( .

Fortunately, there are a couple workarounds:

  1. Create your own TextBox-derived control that fixes the IsInputKey implementation and use that in your controls:
    public class TextBox2 : TextBox {   protected override bool IsInputKey(Keys keyData)   {     return base.IsInputKey(keyData) || keyData == Keys.Back;   } }; 
  2. Cancel NavigationWindow’s CommandBinding for the backspace key by doing this in the constructor of your NavigationWindow-derived class:
    InputBindings.Add(new KeyBinding(ApplicationCommands.NotACommand, new KeyGesture(Key.Back))); 

     

I prefer the latter, as it doesn’t require you to modify your existing WinForms controls. On the other hand, it removes the Backspace gesture for navigating back, but that’s not too bad as I doubt users are actually going to miss it (how many people navigate back in the browser by pressing Backspace anyway?)

I created a small repro and reported this bug through Connect. Feel free to vote for it ;)

Comments