diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor.cs b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor.cs index fa20650559b8..28729c2eb58d 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor.cs +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor.cs @@ -155,6 +155,8 @@ public partial class QuickGrid : IAsyncDisposable // If the QuickGrid is disposed while the JS module is being loaded, we need to avoid calling JS methods private bool _wasDisposed; + private bool _firstRefreshDataAsync = true; + /// /// Constructs an instance of . /// @@ -311,6 +313,13 @@ public async Task RefreshDataAsync() // because in that case there's going to be a re-render anyway. private async Task RefreshDataCoreAsync() { + // First render of Virtualize component will handle the data load itself. + if (_firstRefreshDataAsync && Virtualize) + { + _firstRefreshDataAsync = false; + return; + } + // Move into a "loading" state, cancelling any earlier-but-still-pending load _pendingDataLoadCancellationTokenSource?.Cancel(); var thisLoadCts = _pendingDataLoadCancellationTokenSource = new CancellationTokenSource(); diff --git a/src/Components/test/E2ETest/Tests/QuickGridTest.cs b/src/Components/test/E2ETest/Tests/QuickGridTest.cs index 63ea37319277..6b1c2f0713bf 100644 --- a/src/Components/test/E2ETest/Tests/QuickGridTest.cs +++ b/src/Components/test/E2ETest/Tests/QuickGridTest.cs @@ -166,7 +166,7 @@ public void RowStyleApplied() const p = document.querySelector('tbody > tr:first-child > td:nth-child(5)'); return p ? getComputedStyle(p).textAlign : null;")); } - + [Fact] public void CanOpenColumnOptions() { @@ -208,4 +208,11 @@ public void CanCloseColumnOptionsByHideColumnOptionsAsync() var firstNameSearchSelector = "#grid > table > thead > tr > th:nth-child(2) input[type=search]"; Browser.DoesNotExist(By.CssSelector(firstNameSearchSelector)); } + + [Fact] + public void ItemsProviderCalledOnceWithVirtualize() + { + app = Browser.MountTestComponent(); + Browser.Equal("1", () => app.FindElement(By.Id("items-provider-call-count")).Text); + } } diff --git a/src/Components/test/testassets/BasicTestApp/Index.razor b/src/Components/test/testassets/BasicTestApp/Index.razor index 2caac4101279..8c9e21f163b8 100644 --- a/src/Components/test/testassets/BasicTestApp/Index.razor +++ b/src/Components/test/testassets/BasicTestApp/Index.razor @@ -94,6 +94,7 @@ + diff --git a/src/Components/test/testassets/BasicTestApp/QuickGridTest/QuickGridVirtualizeComponent.razor b/src/Components/test/testassets/BasicTestApp/QuickGridTest/QuickGridVirtualizeComponent.razor new file mode 100644 index 000000000000..b875fad0eee3 --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/QuickGridTest/QuickGridVirtualizeComponent.razor @@ -0,0 +1,36 @@ +@using Microsoft.AspNetCore.Components.QuickGrid +@using System.Linq + +

@ItemsProviderCallCount

+ +
+ + + + +
+ +@code { + internal class Person + { + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + } + + private GridItemsProvider itemsProvider = default!; + + int ItemsProviderCallCount = 0; + + protected override void OnInitialized() + { + itemsProvider = async request => + { + await Task.CompletedTask; + Interlocked.Increment(ref ItemsProviderCallCount); + StateHasChanged(); + return GridItemsProviderResult.From( + items: Enumerable.Range(1, 100).Select(i => new Person { Id = i, Name = $"Person {i}" }).ToList(), + totalItemCount: 100); + }; + } +}