From 58210d4f4732b25c8870b978040b936cf03f748f Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 10:53:45 -0400 Subject: [PATCH 1/8] QuickGrid: Adds EmptyContentTemplate #59078 #50498 --- .../src/EmptyContentTemplate.razor | 6 ++ .../src/EmptyContentTemplate.razor.cs | 10 +++ .../src/QuickGrid.razor | 76 ++++++++++++------- .../src/QuickGrid.razor.cs | 12 +++ 4 files changed, 75 insertions(+), 29 deletions(-) create mode 100644 src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor create mode 100644 src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs 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..571d1990107a --- /dev/null +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs @@ -0,0 +1,10 @@ +using Microsoft.AspNetCore.Components.QuickGrid.Infrastructure; + +namespace Microsoft.AspNetCore.Components.QuickGrid; + +public partial class EmptyContentTemplate +{ + [CascadingParameter] internal InternalGridContext InternalGridContext { get; set; } = default!; + + [Parameter] public RenderFragment ChildContent { get; set; } +} 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..efa6f84c9b35 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) { - RenderRow(__builder, rowIndex++, item); + RenderEmptyRow(__builder, rowIndex++); + } + else + { + 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); @@ -70,32 +88,32 @@ @foreach (var col in _columns) { @{ col.CellContent(__builder, item); } - } - - } + } + +} - private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) - { - - @foreach (var col in _columns) - { - @{ col.RenderPlaceholderContent(__builder, placeholderContext); } - } - +private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) +{ + + @foreach (var col in _columns) + { + @{ col.RenderPlaceholderContent(__builder, placeholderContext); } + } + } private void RenderColumnHeaders(RenderTreeBuilder __builder) +{ + foreach (var col in _columns) { - foreach (var col in _columns) - { - -
@col.HeaderContent
+ +
@col.HeaderContent
- @if (col == _displayOptionsForColumn) - { -
@col.ColumnOptions
- } - - } + @if (col == _displayOptionsForColumn) + { +
@col.ColumnOptions
+ } + } } +} 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) { From 6167d3e7a859cd52962de4134edfbb04b100ca28 Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 11:47:18 -0400 Subject: [PATCH 2/8] Cleanup indentation --- .../src/QuickGrid.razor | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) 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 efa6f84c9b35..8172f36d4930 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor @@ -88,32 +88,32 @@ @foreach (var col in _columns) { @{ col.CellContent(__builder, item); } + } + + } + + private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) + { + + @foreach (var col in _columns) + { + @{ col.RenderPlaceholderContent(__builder, placeholderContext); } } -} - -private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) -{ - - @foreach (var col in _columns) - { - @{ col.RenderPlaceholderContent(__builder, placeholderContext); } - } - - } + } - private void RenderColumnHeaders(RenderTreeBuilder __builder) -{ - foreach (var col in _columns) + private void RenderColumnHeaders(RenderTreeBuilder __builder) { - -
@col.HeaderContent
+ foreach (var col in _columns) + { + +
@col.HeaderContent
- @if (col == _displayOptionsForColumn) - { -
@col.ColumnOptions
- } - + @if (col == _displayOptionsForColumn) + { +
@col.ColumnOptions
+ } + + } } } -} From e708cc9b77888b73767fb24e11bb1fa72134768e Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 11:49:27 -0400 Subject: [PATCH 3/8] cleanup --- .../src/QuickGrid.razor | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 8172f36d4930..088a92f58258 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor @@ -98,11 +98,11 @@ @foreach (var col in _columns) { @{ col.RenderPlaceholderContent(__builder, placeholderContext); } - } - - } + } + + } - private void RenderColumnHeaders(RenderTreeBuilder __builder) + private void RenderColumnHeaders(RenderTreeBuilder __builder) { foreach (var col in _columns) { From 39ba9046db02b0d8f6b77053cbc3a3a01718602a Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 13:01:55 -0400 Subject: [PATCH 4/8] Adds license header to EmptyContentTemplate.razor.cs --- .../src/EmptyContentTemplate.razor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 index 571d1990107a..dfb3cc40070e 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs @@ -1,4 +1,7 @@ -using Microsoft.AspNetCore.Components.QuickGrid.Infrastructure; +// 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; From 504d4530e7560293af6ec5089ffdfff1bbe1a087 Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 13:23:28 -0400 Subject: [PATCH 5/8] Adds documentation to EmptyContentTemplate.razor.cs Makes ChildContent nullable Adds relevant parts of EmptyContentTemplate to PublicAPI.Shipped.txt --- .../src/EmptyContentTemplate.razor.cs | 9 ++++++++- .../src/PublicAPI.Shipped.txt | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) 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 index dfb3cc40070e..2ae14a9417af 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/EmptyContentTemplate.razor.cs @@ -5,9 +5,16 @@ 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!; - [Parameter] public RenderFragment ChildContent { get; set; } + /// + /// 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.Shipped.txt b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt index 1b580b50deff..93ccff1e2d0c 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt @@ -34,6 +34,10 @@ Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Sortable.get -> Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Sortable.set -> void Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Title.get -> string? Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Title.set -> 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.GridItemsProvider Microsoft.AspNetCore.Components.QuickGrid.GridItemsProviderRequest Microsoft.AspNetCore.Components.QuickGrid.GridItemsProviderRequest.ApplySorting(System.Linq.IQueryable! source) -> System.Linq.IQueryable! From 004c9d24a2f83179249dcaed65e005220a420c02 Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 13:39:31 -0400 Subject: [PATCH 6/8] Adds QuickGrid.EmptyContent to PublicAPI.Shipped.txt --- .../src/PublicAPI.Shipped.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt index 93ccff1e2d0c..e4b246abe89a 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt @@ -106,6 +106,8 @@ Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.ChildContent.set Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.Class.get -> string? Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.Class.set -> void Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.DisposeAsync() -> System.Threading.Tasks.ValueTask +Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.EmptyContent.get -> Microsoft.AspNetCore.Components.RenderFragment? +Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.EmptyContent.set -> void Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.ItemKey.get -> System.Func! Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.ItemKey.set -> void Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.Items.get -> System.Linq.IQueryable? From ad244a2c0e64038dab57ae3ded4387d35e0b71dd Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 14:07:25 -0400 Subject: [PATCH 7/8] Moves them to Unshipped --- .../src/PublicAPI.Shipped.txt | 6 ------ .../src/PublicAPI.Unshipped.txt | 8 +++++++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt index e4b246abe89a..1b580b50deff 100644 --- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt +++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/PublicAPI.Shipped.txt @@ -34,10 +34,6 @@ Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Sortable.get -> Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Sortable.set -> void Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Title.get -> string? Microsoft.AspNetCore.Components.QuickGrid.ColumnBase.Title.set -> 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.GridItemsProvider Microsoft.AspNetCore.Components.QuickGrid.GridItemsProviderRequest Microsoft.AspNetCore.Components.QuickGrid.GridItemsProviderRequest.ApplySorting(System.Linq.IQueryable! source) -> System.Linq.IQueryable! @@ -106,8 +102,6 @@ Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.ChildContent.set Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.Class.get -> string? Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.Class.set -> void Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.DisposeAsync() -> System.Threading.Tasks.ValueTask -Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.EmptyContent.get -> Microsoft.AspNetCore.Components.RenderFragment? -Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.EmptyContent.set -> void Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.ItemKey.get -> System.Func! Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.ItemKey.set -> void Microsoft.AspNetCore.Components.QuickGrid.QuickGrid.Items.get -> System.Linq.IQueryable? 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..62c17b315f41 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,10 @@ #nullable enable +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 From ca9d3226c3c5cf9dfb683d6639666f033b4930c9 Mon Sep 17 00:00:00 2001 From: Adam Shortland Date: Tue, 8 Jul 2025 14:53:32 -0400 Subject: [PATCH 8/8] Update Unshipped --- .../src/PublicAPI.Unshipped.txt | 1 + 1 file changed, 1 insertion(+) 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 62c17b315f41..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,5 @@ #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