diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor
new file mode 100644
index 000000000000..cdbd02d520c0
--- /dev/null
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor
@@ -0,0 +1,6 @@
+@namespace Microsoft.AspNetCore.Components.QuickGrid
+@typeparam TGridItem
+
+@{
+ InternalGridContext.Grid.SetEmptyContent(this);
+}
diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs
new file mode 100644
index 000000000000..2ae14a9417af
--- /dev/null
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.AspNetCore.Components.QuickGrid.Infrastructure;
+
+namespace Microsoft.AspNetCore.Components.QuickGrid;
+
+///
+/// A component that is displayed when the has no data available.
+///
+/// The type of data represented by each row in the grid.
+public partial class EmptyContentTemplate
+{
+ [CascadingParameter] internal InternalGridContext InternalGridContext { get; set; } = default!;
+
+ ///
+ /// Defines the content to be rendered by when no data is available.
+ ///
+ [Parameter] public RenderFragment? ChildContent { get; set; }
+}
diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Unshipped.txt b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Unshipped.txt
index a5806f90a9db..d2fc676cbbf1 100644
--- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Unshipped.txt
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Unshipped.txt
@@ -1,4 +1,11 @@
#nullable enable
+~override Microsoft.AspNetCore.Components.QuickGrid.EmptyContentTemplate.BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) -> void
+Microsoft.AspNetCore.Components.QuickGrid.EmptyContentTemplate
+Microsoft.AspNetCore.Components.QuickGrid.EmptyContentTemplate.ChildContent.get -> Microsoft.AspNetCore.Components.RenderFragment?
+Microsoft.AspNetCore.Components.QuickGrid.EmptyContentTemplate.ChildContent.set -> void
+Microsoft.AspNetCore.Components.QuickGrid.EmptyContentTemplate.EmptyContentTemplate() -> void
+Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.EmptyContent.get -> Microsoft.AspNetCore.Components.RenderFragment?
+Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.EmptyContent.set -> void
Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.HideColumnOptionsAsync() -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.RowClass.get -> System.Func?
-Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.RowClass.set -> void
\ No newline at end of file
+Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.RowClass.set -> void
diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor
index 5228ed1d2b00..088a92f58258 100644
--- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor
@@ -20,12 +20,13 @@
@if (Virtualize)
{
+ TItem="(int RowIndex, TGridItem Data)"
+ ItemSize="@ItemSize"
+ OverscanCount="@OverscanCount"
+ ItemsProvider="@ProvideVirtualizedItems"
+ ItemContent="@(item => builder => RenderRow(builder, item.RowIndex, item.Data))"
+ EmptyContent="@EmptyContent"
+ Placeholder="@(placeholderContext => builder => RenderPlaceholderRow(builder, placeholderContext))" />
}
else
{
@@ -41,9 +42,17 @@
{
var initialRowIndex = 2; // aria-rowindex is 1-based, plus the first row is the header
var rowIndex = initialRowIndex;
- foreach (var item in _currentNonVirtualizedViewItems)
+
+ if (EmptyContent != null && _currentNonVirtualizedViewItems.Count == 0)
+ {
+ RenderEmptyRow(__builder, rowIndex++);
+ }
+ else
{
- RenderRow(__builder, rowIndex++, item);
+ foreach (var item in _currentNonVirtualizedViewItems)
+ {
+ RenderRow(__builder, rowIndex++, item);
+ }
}
// When pagination is enabled, by default ensure we render the exact number of expected rows per page,
@@ -63,6 +72,15 @@
}
}
+ private void RenderEmptyRow(RenderTreeBuilder __builder, int rowIndex)
+ {
+
+
+ @EmptyContent
+ |
+
+ }
+
private void RenderRow(RenderTreeBuilder __builder, int rowIndex, TGridItem item)
{
var rowClass = RowClass?.Invoke(item);
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 363ad846cbf7..09923c0048d6 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
@@ -124,6 +124,13 @@ public partial class QuickGrid : IAsyncDisposable
// We cascade the InternalGridContext to descendants, which in turn call it to add themselves to _columns
// This happens on every render so that the column list can be updated dynamically
private readonly InternalGridContext _internalGridContext;
+
+ ///
+ /// Gets or sets a that will be rendered when no data is available to display.
+ /// This allows derived components to specify a default if the user does not specify it.
+ ///
+ protected internal RenderFragment? EmptyContent { get; protected set; }
+
private readonly List> _columns;
private bool _collectingColumns; // Columns might re-render themselves arbitrarily. We only want to capture them at a defined time.
@@ -216,6 +223,11 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
}
}
+ internal void SetEmptyContent(EmptyContentTemplate emptyContentTemplate)
+ {
+ EmptyContent = emptyContentTemplate.ChildContent;
+ }
+
// Invoked by descendant columns at a special time during rendering
internal void AddColumn(ColumnBase column, SortDirection? initialSortDirection, bool isDefaultSortColumn)
{