Make Virtualize recover from having incorrect ItemSize info. Fixes #25915 (#26933)

This commit is contained in:
Steve Sanderson 2020-10-15 23:39:09 +01:00 committed by GitHub
parent 5f2390b990
commit e43041d75f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 0 deletions

View File

@ -253,6 +253,15 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
{
CalcualteItemDistribution(spacerSize, spacerSeparation, containerSize, out var itemsBefore, out var visibleItemCapacity);
// Since we know the before spacer is now visible, we absolutely have to slide the window up
// by at least one element. If we're not doing that, the previous item size info we had must
// have been wrong, so just move along by one in that case to trigger an update and apply the
// new size info.
if (itemsBefore == _itemsBefore && itemsBefore > 0)
{
itemsBefore--;
}
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
}
@ -262,6 +271,15 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
var itemsBefore = Math.Max(0, _itemCount - itemsAfter - visibleItemCapacity);
// Since we know the after spacer is now visible, we absolutely have to slide the window down
// by at least one element. If we're not doing that, the previous item size info we had must
// have been wrong, so just move along by one in that case to trigger an update and apply the
// new size info.
if (itemsBefore == _itemsBefore && itemsBefore < _itemCount - visibleItemCapacity)
{
itemsBefore++;
}
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Threading.Tasks;
using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
@ -211,6 +212,33 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.NotEqual(expectedInitialSpacerStyle, () => topSpacer.GetAttribute("style"));
}
[Fact]
public async Task ToleratesIncorrectItemSize()
{
Browser.MountTestComponent<VirtualizationComponent>();
var topSpacer = Browser.Exists(By.Id("incorrect-size-container")).FindElement(By.TagName("div"));
var expectedInitialSpacerStyle = "height: 0px;";
// Wait until items have been rendered.
Browser.True(() => GetItemCount() > 0);
Browser.Equal(expectedInitialSpacerStyle, () => topSpacer.GetAttribute("style"));
// Scroll slowly, in increments of 50px at a time. At one point this would trigger a bug
// due to the incorrect item size, whereby it would not realise it's necessary to show more
// items because the first time the spacer became visible, the size calculation said that
// we're already showing all the items we need to show.
for (var pos = 0; pos < 1000; pos += 50)
{
Browser.ExecuteJavaScript($"document.getElementById('incorrect-size-container').scrollTop = {pos};");
await Task.Delay(200);
}
// Validate that the top spacer did change
Browser.NotEqual(expectedInitialSpacerStyle, () => topSpacer.GetAttribute("style"));
int GetItemCount() => Browser.FindElements(By.ClassName("incorrect-size-item")).Count;
}
[Fact]
public void CanMutateDataInPlace_Sync()
{

View File

@ -28,6 +28,15 @@
</div>
</p>
<p>
Slightly incorrect item size:<br />
<div id="incorrect-size-container" style="background-color: #eee; height: 500px; overflow-y: auto">
<Virtualize Items="@fixedItems" ItemSize="50">
<div @key="context" class="incorrect-size-item" style="height: 49px; background-color: rgb(@((context % 2) * 255), @((1-(context % 2)) * 255), 255);">Item @context</div>
</Virtualize>
</div>
</p>
<p id="viewport-as-root">
Viewport as root:<br />
<Virtualize Items="@fixedItems" ItemSize="itemSize">