Monday, October 18, 2010

Tab order navigation in WPF

I am using this WPF control that looks like a headered panel. On the header there is a menu, a button and then, underneath, some content that could be anything. I had this request that, when using the Tab key to navigate, the focus should first come to the button, which is not the first control in the header, then jump to the controls in the content and then jump back to the menu. In other words, to make the menu the last controls that can be reached via the Tab key inside this WPF control.

Well, in WPF there is this class called KeyboardNavigation which has some very useful attached properties: TabIndex (which defaults to int.MaxValue) and TabNavigation (which defaults to Continue). As in Windows Forms, one needs to set the TabIndex to control the navigation order, but the TabNavigation property makes it a lot more versatile and clear as well. In my case, I had to do the following:
  1. Set the entire panel control to KeyboardNavigation.TabNavigation=Local. That allowed me to control the tab index inside the control, otherwise the TabIndex value would have been global to the window
  2. Set the TabIndex of the button to 1. That made the button the first thing to be selected in case I use Tab to navigate in the panel
  3. Set the TabIndex of the content to 2. This set the controls in the content as the next controls to be accessed via the Tab key
  4. Set the TabNavigation value of the content to Local. Without this, the TabIndex value would have made no sense. First of all the content panel has IsTabStop to false and, second, any control inside it would have int.MaxValue set as TabIndex which would work globally in the main control.

This example should make it clear how to use the KeyboardNavigation properties. There is one more, called ControlTabNavigation, which has a misleading name and an ambiguous description. It is not related to a control, the Control in the name comes from the Ctrl key. In WPF one can use Ctrl-Tab to navigate an alternative order thus allowing, in this case, to go directly to the menu, then the button and then the controls in the content area.