Skip to content

Fix always true condition in VirtualizingStackPanel.RealizeElements - #22595

Merged
MrJul merged 1 commit into
AvaloniaUI:mainfrom
izakusilov:22192-always-true-condition-in-virtualizingstackpanel
Oct 25, 2026
Merged

MrJul merged 1 commit into
AvaloniaUI:mainfrom
izakusilov:22192-always-true-condition-in-virtualizingstackpanel

Conversation

@izakusilov

Copy link
Copy Markdown
Contributor

What does the pull request do?

Fixes an always-true condition in VirtualizingStackPanel.RealizeElements that caused elements before the anchor element to be recycled even when they are still needed.

What is the current behavior?

RealizeElements decides whether elements before the anchor can be recycled upfront with:

var u = viewport.anchorU;
...
// If the anchor element is at the beginning of, or before, the start of the viewport
// then we can recycle all elements before it.
if (u <= viewport.anchorU)
    _realizedElements.RecycleElementsBefore(viewport.anchorIndex, _recycleElement);

Since u was just assigned viewport.anchorU, the condition is always true, so elements before the anchor are always recycled. When the anchor starts after the start of the viewport, the backward pass then has to realize those same elements again from the recycle pool.

This is visible e.g. when an item is inserted into the visible range and immediately scrolled into view: every visible container above the new item is cleared, removed from the visual tree and re-prepared, and the items can end up in different containers.

What is the updated/expected behavior with this PR?

Elements before the anchor are only recycled upfront when the anchor starts at or before the start of the viewport, as the comment describes. Otherwise they are reused by the backward pass, and anything left over is still recycled after it, as before.

To test: insert an item into the visible range of a virtualized list and call ScrollIntoView on it. The containers of the visible items before it are kept as they are.

How was the solution implemented (if it's not obvious)?

The condition now compares the anchor position against viewport.viewportUStart instead of viewport.anchorU. In the common case (the anchor is the first element that crosses the start of the viewport) the behavior is unchanged.

Added ScrollIntoView_Inserted_Item_Does_Not_Recycle_Elements_Before_It, which fails without the fix. All Avalonia.Controls.UnitTests pass with the fix.

Checklist

Breaking changes

None.

Obsoletions / Deprecations

None.

Fixed issues

Fixes #22192

@maxkatz6 maxkatz6 added bug backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch area-controls labels Oct 25, 2026
@MrJul
MrJul enabled auto-merge October 25, 2026 16:28
@MrJul
MrJul added this pull request to the merge queue Oct 25, 2026
@github-actions

Copy link
Copy Markdown

NuGet packages

The packages for this pull request have been published (workflow run):

Merged via the queue into AvaloniaUI:main with commit b88f813 Oct 25, 2026
13 checks passed
@izakusilov
izakusilov deleted the 22192-always-true-condition-in-virtualizingstackpanel branch October 25, 2026 20:27
@MrJul MrJul added backported-12.1.x and removed backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

always true condition in VirtualizingStackPanel

3 participants