Strange focus behavior for simple WPF ItemsControl

jpierson picture jpierson · Feb 10, 2011 · Viewed 7.2k times · Source

I'm seeing strange behavior when it comes to focus and keyboard navigation. In the example below I have a simple ItemsControl that has been templated so that it presents a list of CheckBoxes bound to the ItemsSource.

<ItemsControl FocusManager.IsFocusScope="True"
              ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

For some strange reason the FocusManager.IsFocusScope="True" assignment causes keyboard focus to fail to be set when checking a checkbox via a mouse click and for focus to jump out of the ItemsControl when a check box is checked using the space bar on the keyboard. Both symptoms seem to point to some strange navigation happening when the checkbox is checked but I'm having a hard time getting to the bottom of it.

This problem occurs if I set any parent element up the visual tree as a focus scope using this method. If I remove the FocusManager.IsFocusScope="True" then the problems go away. Unfortunately I'm seeing this problem in a larger project where I cannot just remove these focus scopes without worrying about other focus related consequences.

Could somebody explain to me the strange behavior I'm seeing? Is this a bug or am I just completely missing something?

Answer

Fredrik Hedblad picture Fredrik Hedblad · Feb 10, 2011

This article explains it very well: http://www.codeproject.com/KB/WPF/EnhancedFocusScope.aspx

For What was FocusScope Designed?

Microsoft uses FocusScope in WPF to create a temporary secondary focus. Every ToolBar and Menu in WPF has its own focus scope.

With this knowledge, we can clearly see why we have those problems:

A toolbar button should not execute commands on itself, but on whatever had focus before the toolbar was clicked. To accomplish this, routed commands ignore the focus from focus scopes and use the 'main' logical focus instead. This explains why routed commands don't work inside focus scopes.

Why does the large text box in the test application screenshot still display a caret? I don't know the answer to this - but why shouldn't it? Granted, the text box doesn't have the keyboard focus (the small text box in the WPF focus scope has that); but it still has the main logical focus in the active Window and is the receiver of all routed commands.

And this part covers the behavior you're seeing

Why does the keyboard focus move to the large text box when you tab to the CheckBox in the WPF focus scope and press Space to toggle it?

Well, this is exactly what you expect when you click a menu item or a toolbar: the keyboard focus should return to the main focus. All ButtonBase-derived controls will do this.