Fix five Avalonia UI regressions: mouse navigation, derived types, Enter, Delete, Analyze in the Analyzer pane - #4039
Open
christophwille wants to merge 5 commits into
Open
Conversation
DerivedTypesEntryNode.Filter reported Recurse, but the cascade's Recurse handling force-loads the entry's lazy children and hides the entry when all of them are hidden. A leaf derived type has no children, so every entry under "Derived Types" ended up hidden, and the hiding propagated up the whole derived chain. The WPF tree showed these entries as matches; Match restores that and also keeps the entries' children lazy instead of eagerly scanning the assembly list for each level of the chain. Assisted-by: Claude:claude-fable-5:Claude Code
Avalonia 12 treats plain Enter/Space on a ListBoxItem as selection input: the container marks the KeyDown handled before it bubbles, so SharpTreeView.OnKeyDown never saw the keys and its activation handling (navigate to the member from an analyzer row, toggle a checkable row) was dead. Override ShouldTriggerSelection -- the extension point added for this in Avalonia 12 -- to suppress the selection trigger exactly for the case OnKeyDown activates instead: a single selected row that is the row the key landed on. Multi-row selections keep the default collapse-to-focused-row behaviour. Assisted-by: Claude:claude-fable-5:Claude Code
WPF translated XButton1/XButton2 into BrowseBack/BrowseForward commands by itself, so the WPF frontend got the behaviour for free and the buttons never reached the control under the pointer as a click. Avalonia has no such translation and KeyBinding cannot express pointer buttons, so only Alt+Left / Alt+Right survived the migration. MainWindow now swallows the X-button press while it tunnels (Dock would otherwise activate the pane under the pointer, AvaloniaEdit would focus the editor or toggle a folding marker) and routes the release to the existing DockWorkspace navigation commands. Navigating also no longer moves the active pane to the editor: the history target is usually the already-active tab, and Dock's ActiveDockable setter re-runs InitActiveDockable -> SetFocusedDockable even for an unchanged value, so re-activating it only moved the focus. WPF's ActiveTabPage setter was a no-op for the same value. Assisted-by: Claude:claude-fable-5:Claude Code
The WPF SharpTreeView bound ApplicationCommands.Delete at class level, so Delete deleted the top-level selection of any tree whose nodes opt in via CanDelete/Delete -- which is how a top-level analyzer entry was removed from the Analyzer pane. The Avalonia tree never received that binding; only the assembly list pane carried a hand-rolled Delete handler for assemblies, so the analyzer pane lost the key entirely even though its nodes still implement the deletion overrides. Moving the gesture back into SharpTreeView restores it for every tree and lets the pane-specific handler (with its own reselect logic) go. Assisted-by: Claude:claude-fable-5:Claude Code
christophwille
force-pushed
the
fix/ui-regressions-4027-4028-4030
branch
from
August 22, 2026 08:20
71b732f to
9132a09
Compare
The port dropped IMemberTreeNode from AnalyzerEntityTreeNode, so the member-based context-menu entries (Analyze, Copy name, ...) no longer recognised analyzer rows and a result row could not be promoted to a top-level entry. Top-level rows keep the entry hidden: re-analysing them is a no-op, and Remove is the entry for those rows. Assisted-by: Claude:claude-fable-5:Claude Code
siegfriedpammer
approved these changes
Aug 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Five UI regressions from the Avalonia migration (the fourth and fifth, Delete and Analyze in the Analyzer pane, were reported in the #4030 thread), one commit each, each with a headless regression test that was shown red before the fix.
Fixes #4027
Fixes #4028
Fixes #4030
Mouse4 / Mouse5 no longer navigate back / forward (#4027)
WPF translated the extra mouse buttons into
BrowseBack/BrowseForwardcommands by itself, so they never reached the control under the pointer as a click; Avalonia has no such translation andKeyBindingcannot express pointer buttons, so only Alt+Left / Alt+Right survived the migration.MainWindownow swallows theXButton1/XButton2press while it tunnels (otherwise Dock activates the pane under the pointer and AvaloniaEdit focuses the editor or toggles a folding marker) and routes the release to the existingDockWorkspace.NavigateBackCommand/NavigateForwardCommand. Navigating also no longer moves the active pane to the editor: the history target is usually the already-active tab, and Dock'sActiveDockablesetter re-runsSetFocusedDockableeven for an unchanged value, soApplyNavigationTargetonly activates a tab that is not active yet (WPF'sActiveTabPagesetter was a no-op for the same value).Derived types not shown in tree (#4028)
DerivedTypesEntryNode.FilterreportedFilterResult.Recurse, but the filter cascade's Recurse handling force-loads the node's lazy children and hides the node when all of them are hidden. A leaf derived type has no children, so every entry under "Derived Types" ended up hidden, and the hiding propagated up the whole chain. ReportingMatch(what the WPF tree effectively did, since the tree ignores the search term) restores the entries and also keeps derived chains lazy instead of eagerly scanning the assembly list for every level.Enter does nothing on a selected tree row (#4030)
Avalonia 12's default key selection triggers treat plain Enter/Space on a
ListBoxItemas selection input and mark theKeyDownhandled before it bubbles, so the activation handling inSharpTreeView.OnKeyDown(navigate to the member from an analyzer row, toggle a checkable row) never saw those keys.SharpTreeViewnow overridesShouldTriggerSelection— the Avalonia 12 extension point for exactly this — to suppress the selection trigger precisely for the caseOnKeyDownactivates instead: a single selected row that is the row the key landed on. Multi-row selections keep the default collapse-to-focused-row behaviour.Delete does nothing on a selected analyzer row (#4030, follow-up report)
The WPF
SharpTreeViewboundApplicationCommands.Deleteat class level, so Delete removed the top-level selection of any tree whose nodes opt in throughCanDelete/Delete-- which is how a top-level analyzer entry was removed from the Analyzer pane. The Avalonia tree never received that binding; only the assembly list pane carried a hand-rolled Delete handler for assemblies. The gesture now lives inSharpTreeView.OnKeyDownagain (delete the top-level selection when every node in it is deletable, then reselect the nearest survivor), which restores it for the analyzer pane and lets the pane-specific handler go.Analyze missing from the Analyzer pane's context menu (#4030 thread, second follow-up report)
The WPF
AnalyzerEntityTreeNodeimplementedIMemberTreeNode, which is what the "Analyze" entry (and "Copy name") keys off, so right-clicking a result row in the Analyzer pane offered Analyze and promoted that row's entity to a new top-level entry. The Avalonia port dropped the interface from the node, so no analyzer row ever showed the entry. The interface is back on the node; as in WPF, top-level analyzer rows keep Analyze hidden (re-analysing them is a no-op, Remove is the entry for those rows).Verification
Full
ILSpy.Testssuite green locally, including the new regression tests (Mouse_Back_And_Forward_Buttons_Navigate_The_History,Mouse_Back_Button_Press_Does_Not_Reach_The_Control_Under_The_Pointer,Browse_Back_Keeps_The_Active_Pane,Derived_Type_Entries_Stay_Visible_When_The_DerivedTypes_Node_Is_Expanded,Enter_Activates_The_Selected_Analyzer_Node,Delete_Removes_The_Selected_Top_Level_Analyzer_Node,Analyze_Promotes_An_Analyzer_Result_Row_To_A_Top_Level_Entry,Analyze_Is_Hidden_For_A_Top_Level_Analyzer_Row).Written by an AI agent (Claude) on Christoph's behalf.