dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.08k stars 1.17k forks source link

TabControl selection changes triggers with no reason #8293

Closed Drexel2k closed 4 months ago

Drexel2k commented 1 year ago

Description

Hello,

In my project I use the MaterialDesign for XAML controls, which don't have ribbons. So I create a TabControl with ToolBarTrays with some buttons in the TabItems. When I click on a tab, then to another tab and click on a button on the ToolBarTray it switches back to the last tab.

I first opened an issue in the MaterialDesign for XAML repo, but then I noticed that it occurs also with the standard controls and it is not a material design problem: https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/issues/3337

I build a minimal example for it. In my real app, this happens only one time or is prevented when i click a second time on the current tab. In the minimal example, it happens all the time.

You can get the minimal example here:

https://github.com/Drexel2k/WpfApp1

Best regards Matthias

Reproduction Steps

  1. Start the app with Debug/AnyCPU.
  2. Click on Playlists tab.
  3. Click on Templates tab.
  4. Click there on the New Template Button.

Now it switches back to Playlists Tab, also the SelectionChanged fires, you can set a breakpoint on the event listener in the MainWindopws.xaml.cs on line 19. In my real MVVM app, also the TabIndex binding triggers.

Expected behavior

The tab shouldn't change when I click on a button in the ToolBarTray

Actual behavior

The TabControl switches back to the last active tab.

Regression?

No response

Known Workarounds

Remove the ToolBarTray solves the problem.

Impact

You can't use the ToolBarTray within TabControls.

Configuration

.NET 6 Edition Windows 11 Pro Version 22H2 OS Build 22621.2428 Windows Feature Experience Pack 1000.22674.1000.0 Processor 13th Gen Intel(R) Core(TM) i7-13700KF 3.40 GHz RAM 32,0 GB (31,9 GB verwendbar) Systemtyp 64-Bit-Betriebssystem, x64-basierter Prozessor

Other information

No response

miloush commented 1 year ago

This is a focus issue. The toolbars have their own focus scope. You can notice that if you click on a tab header twice so that you get the focus visual around it (dotted rectangle), then the focus will stay on the tab headers and not on the buttons. This will properly keep track of the focused tab and pressing the buttons will not switch the tabs.

That gives you several possible workarounds while using tool bars in tab controls:

  1. set FocusManager.IsFocusScope="False" on the toolbars (not on the trays).
  2. turn on the Switch.System.Windows.Controls.TabControl.SelectionPropertiesCanLagBehindSelectionChangedEvent compatibility switch
  3. handle the tab item's GotKeyboardFocus and call FocusManager.SetFocusedElement(window, tabitem)

It does feel like this should work better, although I am not quite sure where the fix should be yet.

miloush commented 1 year ago

Most likely TabItem.OnPreviewGotKeyboardFocus for the cases when e.Handled = true should call FocusManager.SetFocusedElement on its focus scope, possibly only if not within. This might be a high impact change.

Drexel2k commented 1 year ago

Thank you for the information! For now I have removed the ToolBarTray as I don't need them necessarily. Maybe I try it in a later release of my app again or when the behaviour is fixed.