Repository navigation
TreeView: clicking a row after scrolling away from the selection jumps the viewport and reselects the previous rowΒ #25796
Description
Current behavior π
In a single-selection TreeView with enough rows to be virtualized, select a row, scroll until that row is out of view, then click another row:
- The viewport jumps back toward the previously selected row (by about 1,200β1,500 px in the repro) instead of staying where it was.
SelectionChangedis raised with the previous row inAddedItemswhile the clicked row is being selected, so the previous row is briefly selected again.
Expected behavior π―
- Clicking a visible row selects it in place; the viewport does not move.
- Only the clicked row is reported in
AddedItems.
How to reproduce it (as minimally and precisely as possible) π¬
Repro: k473_LVSSIV.zip
The app builds a TreeView with 30 expanded groups of 25 rows (about 780 visible rows), with IsExpanded and IsSelected two-way bound. A log panel at the bottom records each click ([CLICK]), each SelectionChanged ([SEL]) and any viewport change within a second of a click ([BUG?]).
dotnet run --project Uno120513Repro -f net10.0-desktop
- Click a row.
- Wheel-scroll down a few screens, until that row is out of view.
- Click another visible row: the viewport jumps, and the log shows a
[BUG?]line with the offset change, and a[SEL]line adding the previous row.
The same scenario is automated: the Auto check button (or --auto on the command line) runs it 20 times with injected mouse clicks and reports JUMP and PREVIOUS-RESELECTED for each iteration. With --auto the app prints [AUTO] lines to the console and exits with the failure count:
dotnet run --project Uno120513Repro -f net10.0-desktop -- --auto
On Uno.WinUI 7.0.0-dev.2494 all 20 iterations report JUMP and PREVIOUS-RESELECTED.
Workaround π οΈ
None known.
Affected platforms π±π»π₯οΈ
All platforms π (reproduced on Desktop (Windows); the code involved is shared by all platforms)
Uno.Sdk version (and other relevant versions) π¦
Uno.Sdk 7.0.0-dev.95 (Uno.WinUI 7.0.0-dev.2494). Also seen on 6.6 and 6.7.
IDE version π§βπ»
No response
Anything else we need to know? π¬
In single selection, selecting a node unselects the previous one through TreeViewViewModel.NotifyContainerOfSelectionChange. When the previous node has no container, an Uno-only fallback there (not in WinUI) assigns the node to TreeViewList.SelectedItem regardless of whether it is being selected or unselected. For an unselection, that selects the previous node again, and Selector scrolls it into view; the clicked node's own selection then scrolls back.
Fixing only that fallback exposes a second problem when TreeViewItem.IsSelected is two-way bound, as in the repro: while the previous row has no container, nothing writes the unselection back to its IsSelected, so the data still says true. When the row is scrolled back into view, TreeViewList.PrepareContainerForItemOverride honors that value (the workaround for #15214) and the row takes the selection back from the clicked one.
Activity