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) {