1

I tried to <Virtualize> a list of a thousand items showing several per row, with display: inline-block. The result in Blazor kinda works, but as the user scrolls, it seems to remove items from the DOM at the beginning and add them at the end in an arbitrary amount, causing the displayed items to change in position unexpectedly, giving the user a bad experience: the items are "reflowed", and an item that used to be in the third position in its row might now be in the first, second, or fourth position in its new row. The result is that the user scrolls and when a "update" of the items happen, the user loses track of the items that should still be shown in the viewport.

I am indeed using @key on the child content of the Virtualize component, and specifying an explicit ItemSize on the Virtualize component doesn't seem to help either.

Demo: Scroll down slowly and note the items by their six-character hex ID. After scrolling down a bit but before the first reflow, you'll see the gap for the last item.:

before first reflow

Then, after scrolling down just a little bit more, the reflow happens.

after first reflow

Expected behavior: The user should see the same items that were previously near the bottom of the viewport now near the top, in the same horizontal position, with new items following them.

Actual Behavior: The user sees some of the same items from before, but in different horizontal locations. Other items are unexpectedly above the viewport. Thus the user loses perceptual context of where they just scrolled from.

Also, note in the example first screenshot above that the last row before reflow is only partial till it is fully scrolled into view and triggers a rerender/reflow, as if it can't tell that there is room for a few more items. I suspect this symptom is closely related.

Any ideas on how to coax the Virtualize component into allowing multiple items per row with consistency as scrolling? I can't believe this is really the designed behavior. I previously thought I fixed a similar issue here, but now I realize that this earlier issue was only part of the problem.

Patrick Szalapski
  • 8,738
  • 11
  • 67
  • 129
  • I would give the @key directive a try. – enet Jun 11 '22 at 08:47
  • 1
    The issue facing here is you not providing rows you are providing data that is used in columns/wrap flow. For Virtualize to work it uses a fixed height row and calculates the height of a div that is before and after the visible components. Virtualize does not know your grouping items per row so its not removing 4 at a time which would solve your scroll issue. So Maybe a grouping query to provide a row of 4 items. – Brian Parker Jun 11 '22 at 10:16
  • Try giving your `img` elements an explicit height and width. A big part of the problem on your page is that the image size is only realized after the image is downloaded, causing the virtualize logic to get out of whack. – Kirk Woll Jun 11 '22 at 14:38
  • You might want to look at the Linq Chunk method. This will give you groupings of N. Let the Virtualize component treat the groups as rows. You may still need a model to put the groups in for @key or you will run back into the other problem. – Brian Parker Jun 11 '22 at 17:15
  • @KirkWoll, I have already tried to put a maxHeight on the container `
      ` and then supplying that number to ItemHeight--it didn't change anything.
    – Patrick Szalapski Jun 12 '22 at 23:53
  • @BrianParker, I'm guessing you are right and I get it, but I don't want to predefine the chunk size, as it will dynamically change with zoom level or window/viewport width. No way to do this with ``? – Patrick Szalapski Jun 12 '22 at 23:54
  • @PatrickSzalapski I thought this may be the issue. This is way outside the intent of the component. If you employ some simple javascript you could get the dimensions of the viewport and calculate the chunk size... – Brian Parker Jun 13 '22 at 00:00

0 Answers0