Fix InitialItemIndex viewport underfill for small indices#67936
Open
ilonatommy wants to merge 5 commits into
Open
Fix InitialItemIndex viewport underfill for small indices#67936ilonatommy wants to merge 5 commits into
ilonatommy wants to merge 5 commits into
Conversation
ilonatommy
temporarily deployed
to
copilot-pat-pool
July 21, 2026 12:21 — with
GitHub Actions
Inactive
ilonatommy
temporarily deployed
to
copilot-pat-pool
July 21, 2026 12:21 — with
GitHub Actions
Inactive
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a Blazor Virtualize/QuickGrid startup issue where small InitialItemIndex values could leave the viewport bottom underfilled until the user scrolls. It does this by deferring “leading overscan” (items reserved above the target) until the component has received its first spacer/measurement feedback, and adds E2E coverage to prevent regressions.
Changes:
- Add a
_hasSpacerFeedbackflag to detect when initial spacer observer feedback has occurred and use it to avoid reserving pre-target overscan during the initial unmeasured window seed. - Mark spacer feedback as received when
OnBeforeSpacerVisible/OnAfterSpacerVisiblerun, restoring the normal overscan-before-target behavior after measurement. - Add E2E tests asserting that both
QuickGridandVirtualizefill the viewport for smallInitialItemIndexvalues (including a small overscan scenario), plus minor test-asset updates to support the scenario.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Components/Web/src/Virtualization/Virtualize.cs | Defers leading overscan until spacer feedback exists to prevent initial viewport underfill. |
| src/Components/test/testassets/BasicTestApp/VirtualizationAnchorMode.razor | Adds a UI toggle to set a small overscan to reproduce/validate the scenario. |
| src/Components/test/testassets/BasicTestApp/QuickGridTest/QuickGridScrollComponent.razor | Adjusts rendered item styling in the scroll/initial-index test component used by E2E coverage. |
| src/Components/test/E2ETest/Tests/VirtualizationTest.cs | Adds E2E assertions ensuring initial-index loads cover the viewport bottom with real items for both QuickGrid and Virtualize. |
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.
Fixes #67933
Problem
Loading a
Virtualize(orQuickGrid) at a smallInitialItemIndexe.g. 10 rendered only a few rows below the target and left a blank gap at the bottom of the viewport, with no items and no placeholders. The gap only filled once the user manually scrolled.Example: a 300px container with fixed 50px rows fits 6 rows.
InitialItemIndex=10rendered only items 10–13, leaving room for 14 and 15 empty.Root cause
InitialItemIndexaligns the target row to the top of the viewport.On a fresh load, before any spacer-observer measurement has arrived,
MoveWindowToContainonly has a minimal seed capacity (OverscanCount * 2 + 1). It still reservedOverscanCountrows before the target. Because the target is top-aligned, those leading rows land off-screen (above). The small seed window no longer has enough rows to cover the area below the target.• QuickGrid (default
OverscanCount = 3) -> seed of 7 rows, 3 wasted above -> underfills.• Pure Virtualize (
OverscanCount = 15) -> seed of 31 rows, big enough to mask the issue in most cases.The window would only correct itself via a spacer-observer callback, which is suppressed during a programmatic scroll.
Fix
Don't reserve any rows above the target until the container has actually been measured. A new
_hasSpacerFeedbackflag records whether that first measurement has happened. Before it does,MoveWindowToContainstarts the rendered window right at the target row, so all of the estimated rows go below it and fill the viewport. After the measurement arrives, the flag flips and the normal rows-above-the-target behavior resumes.