Incorrect focus scope causing stack overflow with routed commands
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
### Description
I'll use the minimal reproduction app below as an example here. When the button is clicked, a stack overflow happens because the focus scope is incorrectly determined for the button:
1. When clicked, the button gets the focus. `FocusManager` will find its focus scope to update `FocusedElement` property
2. `FocusManager` finds the focus scope by following the logical parent first, and then the visual parent. For the button, it will look at the `StackPanel`, `ContentControl`, `DockPanel`, and eventually deciding that the focus scope should be the `Window`. `FocusManager` the sets `FocusedElement` for the window.
3. At some point, `CommandManager.RaiseRequerySuggested` is dispatched, which raises `CanExecute` for the routed command on the menu item. Because the menu item itself doesn't have command bindings for `CanExecute`, it will find a parent in the tree that can handle it starting from the currently focused element
4. `CommandManager.OnCanExecute` is called on the button's visual parents. When it comes to the `Menu`, since the menu doesn't handle the routed command either, it will try to transfer the event to the focused element in its parent focus scope
5. The `Menu`'s parent focus scope is the `Window`, and the window's focused element is the button. So instead of going up the visual tree, the routed command bubbling actually goes back down. The search for a command binding enters a recursion
Generally speaking, this issue doesn't necessarily need to happen with a menu, but can be anything that is set to be a focus scope. A stack overflow will happen as long as the focus scope is inside a template (can also be a control template), the focused control is outside the template, and there's a control that hooks into can execute changed events for routed commands (a menu item, a button or a hyperlink)
### Reproduction Steps
Just create a WPF app with the following XAML in the main window. Open the menu and click on the button to trigger the overflow
```XML
```
### Expected behavior
No stack overflow. The window's focused element should be null while the menu's focused element should be the button
### Actual behavior
It causes a stack overflow. The window's focused element is the button and the menu's focused element is null
### Regression?
_No response_
### Known Workarounds
_No response_
### Impact
_No response_
### Configuration
.NET 8
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.