I think I can explain this after digging into the framework source code.
1. After clicking, the MenuBase and ButtonBase class will try to restore keyboard focus to previous focused element by calling Keyboard.Focus(null). This will set keyboard focus to top level main window.
Since Window is a FocusScope, this will set focus to main window's FocusedElement. Normally we don't expect a click will change the focus, that's where the confusion come from. But this behavior makes sense:
1) MenuBase works in a open-dismiss way. It should not have the focus after clicking. Actually I think they should not get focus at all, like in Win32 or Win forms. But this is another topic.
2) Normally after clicking a button, we're not likely to click it again. So it's naturaly to restore the focus to previously focused element.
2. The nested FocusScope. It's not actually that complex as we expected. Whenever an UIElement receives keyboard focus, it will find its DIRECT parent focus scope, and set this focus scope's FocusedElement
to itself. Keyboard focus leaves the focus scope will do nothing.
Consider the check box sample you provided:
1) If you set IsFocusScope="true" on StackPanel, focus the check box will set StackPanel's FocusedElement to check box, and main window's FocusedElement remains unchanged - ListViewItem; After clicking
the check box, because of Keyboard.Focus(null) called, the keyboard focus will set to previous ListViewItem.
2) If you remove IsFocusScope="true" on StackPanel, focus the check box will set main window's FocusedElement to the check box. Keyboard.Focus(null) will set the focus back to the check box.
If you want both IsFocusScope="true" and no keyboard focus change after clicking the check box, add the following code to your window class (of course you need to add x:Name="checkBox" in the XAML
Wow long discussion on this... I had to figure some of this out early on, and I thought I chip in with what I discovered. I found some errors in the documentation that I don't think have been corrected.
Based on my testing the correct explanation of command routing when no target is set is:
The element within the Windows focus scope that has logicalfocus
will be used as the command target.
Note that it's the windows focus scope not the active focus scope. And it's logical focus not keyboard focus.
When it comes to command routing, FocusScopes remove any item you place them on and it's child elements from the command routing path.
So if you create a focus scope in your app and want a command to route in to it you will have to set the command target manually.
Or, you can not use FocusScopes other than for toolbars, menus etc and handle the container focus problem manually.
The above is pretty much covered in the posts above, but I think this states it a little clearer. If not... sorry for butting in.<g>