-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Don't enter a KeyboardNavigationMode.None group via its active element #22154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,10 +23,16 @@ internal static class TabNavigation | |
| if (IsTabStop(container)) | ||
| return container; | ||
|
|
||
| // Using ActiveElement if set | ||
| var activeElement = GetActiveElement(container); | ||
| if (activeElement != null) | ||
| return GetNextTab(null, activeElement, true); | ||
| // Using ActiveElement if set. A None group never hands out an element | ||
| // inside itself, not even a remembered one: ItemsControl records the | ||
| // last focused child as the active element, so without this an | ||
| // ItemsControl with TabNavigation="None" is still entered. | ||
| if (tabbingType != KeyboardNavigationMode.None) | ||
| { | ||
| var activeElement = GetActiveElement(container); | ||
| if (activeElement != null) | ||
| return GetNextTab(null, activeElement, true); | ||
| } | ||
| } | ||
| else | ||
| { | ||
|
|
@@ -95,8 +101,11 @@ internal static class TabNavigation | |
|
|
||
| if (e == null) | ||
| { | ||
| // Using ActiveElement if set | ||
| var activeElement = GetActiveElement(container); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, this code is directly from WPF: I'd like to understand why we'd want to diverge from WPF.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed that matching WPF should be the default, so I tried WPF's approach first: gate the write the way It doesn't survive here. Avalonia uses Gating the write on So the divergence is forced by that property carrying two responsibilities in Avalonia. The read side was where I could fix it without disturbing virtualization. The cleaner long term option is to split the two concerns, a navigation active element and a separate virtualization anchor. Then Avalonia could take WPF's write gate verbatim and both of these hunks would go back to matching WPF exactly. That's a bigger change and your call, and I'm happy to do it that way if you'd prefer. |
||
| // Using ActiveElement if set, except for None groups, which never hand | ||
| // out an element inside themselves. See the matching note in GetNextTab. | ||
| var activeElement = tabbingType == KeyboardNavigationMode.None | ||
| ? null | ||
| : GetActiveElement(container); | ||
| if (activeElement != null) | ||
| return GetPrevTab(null, activeElement, true); | ||
| else | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code comes directly from WPF:
https://github.com/dotnet/wpf/blob/360950b3ceb503d68bbb2fbc2ab9271e4cda90a5/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/KeyboardNavigation.cs#L2090-L2093
Does this issue also reproduce on WPF?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it doesn't reproduce on WPF, and the reason is that WPF gates the write rather than the read.
KeyboardNavigation.UpdateActiveElementonly records an active element forOncegroups:https://github.com/dotnet/wpf/blob/360950b3ceb503d68bbb2fbc2ab9271e4cda90a5/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/KeyboardNavigation.cs#L948-L960
That's the only write path:
SetActiveElementis private with a single caller, andSetTabOnceActiveElementis only called from it. So in WPF aNonecontainer never has an active element, and the code you linked never gets the chance to follow one.Avalonia records it unconditionally, in three places:
ItemsControl.OnGotFocus(ItemsControl.cs:543), and the selection anchor inSelectingItemsControl.cs:539and:971.The selection path is the one in the report. The ListBox has an active element as soon as an item is selected, without ever being focused. That is also why the reporter's TreeView looked correct: it had no selected item, so nothing recorded one.