From 144d439eedbbfc039145721578a2bd486f458eed Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 29 May 2026 11:16:12 -0400 Subject: [PATCH 1/2] [11.0 P5] Blazor Preview 5 QuickGrid updates --- aspnetcore/blazor/components/quickgrid.md | 212 +++++++++++++++--- .../aspnetcore-11/includes/blazor.md | 102 +++++++++ 2 files changed, 280 insertions(+), 34 deletions(-) diff --git a/aspnetcore/blazor/components/quickgrid.md b/aspnetcore/blazor/components/quickgrid.md index 44038002e7cb..50aa4e28b86e 100644 --- a/aspnetcore/blazor/components/quickgrid.md +++ b/aspnetcore/blazor/components/quickgrid.md @@ -29,7 +29,35 @@ For various QuickGrid demonstrations, see the [**QuickGrid for Blazor** sample a To implement a `QuickGrid` component: -:::moniker range=">= aspnetcore-9.0" +:::moniker range=">= aspnetcore-11.0" + + + +* Specify tags for the `QuickGrid` component in Razor markup (`...`). +* Name a queryable source of data for the grid. Use ***either*** of the following data sources: + * : A nullable `IQueryable`, where `TGridItem` is the type of data represented by each row in the grid. + * : A callback that supplies data for the grid. +* `QueryParameterNamePrefix`: The parameter from which the page and sorting URL parameters are derived. The default value is an empty string, which results in query parameters named "`page`", "`sort`", and "`order`". Setting a prefix for the preceding query string parameters allows the use of multiple `QuickGrid` components on the same page without their URL parameters conflicting with each other. For more information, see the [Pagination modes](#pagination-modes) and [Multiple grids on the same page](#multiple-grids-on-the-same-page) sections. +* : An optional CSS class name. If provided, the class name is included in the `class` attribute of the rendered table. +* : A theme name (default value: `default`). This affects which styling rules match the table. +* : If true, the grid is rendered with virtualization. This is normally used in conjunction with scrolling and causes the grid to fetch and render only the data around the current scroll viewport. This can greatly improve the performance when scrolling through large data sets. If you use , you should supply a value for and must ensure that every row renders with a constant height. Generally, it's preferable not to use if the amount of data rendered is small or if you're using pagination. +* : Only applicable when using . defines an expected height in pixels for each row, allowing the virtualization mechanism to fetch the correct number of items to match the display size and to ensure accurate scrolling. +* : Optionally defines a value for `@key` on each rendered row. Typically, this is used to specify a unique identifier, such as a primary key value, for each data item. This allows the grid to preserve the association between row elements and data items based on their unique identifiers, even when the `TGridItem` instances are replaced by new copies (for example, after a new query against the underlying data store). If not set, the `@key` is the `TGridItem` instance. +* : Defines how many additional items to render before and after the visible region to reduce rendering frequency during scrolling. While higher values can improve scroll smoothness by rendering more items off-screen, a higher value can also result in an increase in initial load times. Finding a balance based on your data set size and user experience requirements is recommended. The default value is `3`. Only available when using . +* : Optionally links this `TGridItem` instance with a model, causing the grid to fetch and render only the current page of data. This is normally used in conjunction with a component or some other UI logic that displays and updates the supplied instance. includes API for interacting with the current zero-based page index, the number of items on each page, the zero-based index of the last page, and the total number of items across all pages. +* In the QuickGrid child content (), specify s, which represent `TGridItem` columns whose cells display values: + * : Defines the value to be displayed in this column's cells. + * : Optionally specifies a format string for the value. Using requires the `TProp` type to implement . + * : Indicates whether the data should be sortable by this column. The default value may vary according to the column type. For example, a is sorted if any parameter is specified. + * : Indicates the sort direction if is `true`. + * : Indicates whether this column should be sorted by default. + * : If specified, virtualized grids use this template to render cells whose data hasn't been loaded. + * : An optional template for this column's header cell. If not specified, the default header template includes the , along with any applicable sort indicators and options buttons. + * : Title text for the column. The title is rendered automatically if isn't used. + +:::moniker-end + +:::moniker range=">= aspnetcore-9.0 < aspnetcore-11.0" * Specify tags for the `QuickGrid` component in Razor markup (`...`). * Name a queryable source of data for the grid. Use ***either*** of the following data sources: @@ -80,8 +108,12 @@ To implement a `QuickGrid` component: For example, add the following component to render a grid. +:::moniker range="< aspnetcore-11.0" + For Blazor Web Apps, the `QuickGrid` component must adopt an [interactive render mode](xref:blazor/components/render-modes#render-modes) to enable interactive features, such as paging and sorting. +:::moniker-end + `PromotionGrid.razor`: :::moniker range=">= aspnetcore-9.0" @@ -100,22 +132,20 @@ Access the component in a browser at the relative path `/promotion-grid`. There aren't current plans to extend QuickGrid with features that full-blown commercial grids tend to offer, for example, hierarchical rows, drag-to-reorder columns, or Excel-like range selections. If you require advanced features that you don't wish to develop on your own, continue using third-party grids. -## Sort by column - -The `QuickGrid` component can sort items by columns. In Blazor Web Apps, sorting requires the component to adopt an [interactive render mode](xref:blazor/components/render-modes#render-modes). +## Page items with a `Paginator` component -Add `Sortable="true"` () to the tag: +:::moniker range=">= aspnetcore-11.0" -```razor - -``` +The `QuickGrid` component can page data from the data source. -In the running app, sort the QuickGrid column by selecting the rendered column title. +:::moniker-end -## Page items with a `Paginator` component +:::moniker range="< aspnetcore-11.0" The `QuickGrid` component can page data from the data source. In Blazor Web Apps, paging requires the component to adopt an [interactive render mode](xref:blazor/components/render-modes#render-modes). +:::moniker-end + Add a instance to the component's `@code` block. Set the to the number of items to display per page. In the following example, the instance is named `pagination`, and ten items per page is set: ```csharp @@ -128,51 +158,175 @@ Set the `QuickGrid` component's ``` - +:::moniker range=">= aspnetcore-11.0" + +To provide a UI for pagination, add a [`Paginator` component](xref:Microsoft.AspNetCore.Components.QuickGrid.Paginator) above, below, or both above and below the `QuickGrid` component. Set the to `pagination`: + +:::moniker-end + +:::moniker range="< aspnetcore-11.0" To provide a UI for pagination, add a [`Paginator` component](xref:Microsoft.AspNetCore.Components.QuickGrid.Paginator) above or below the `QuickGrid` component. Set the to `pagination`: +:::moniker-end + ```razor ``` In the running app, page through the items using a rendered `Paginator` component. +:::moniker range="< aspnetcore-11.0" + QuickGrid renders additional empty rows to fill in the final page of data when used with a `Paginator` component. In .NET 9 or later, empty data cells (``) are added to the empty rows. The empty rows are intended to facilitate rendering the QuickGrid with stable row height and styling across all pages. -## Open and return from a details page with a paged QuickGrid component +:::moniker-end -A paged QuickGrid component can open a details page for a record and return to the correct page of results using the approach in this section. +:::moniker range=">= aspnetcore-11.0" + + + +`GetPageUrl` returns a URL with the one-based page number. Page index 0 (page 1) omits the query parameter entirely. + +:::moniker-end - + +Multiple `QuickGrid` components on the same page require unique `QueryParameterNamePrefix` values to avoid query string conflicts. The default prefix is an empty string, producing parameters named `page`, `sort`, `order`. For example, setting the prefix to "`cities`" produces `cities_page`, `cities_sort`, and `cities_order`. + +Each `QuickGrid` must have its own `PaginationState` instance. Multiple grids must not share a `PaginationState` if they have different prefixes—the last grid to render overwrites the query parameter name on the shared state, causing the `Paginator` to read from the wrong parameter. + +In the following example, each `QuickGrid` requires a unique `QueryParameterNamePrefix`. The first `QuickGrid` uses the default empty string prefix, while the second one sets `cities` as the prefix: + +```razor + + ... + + + + + + ... + + + +``` + +In the following query string: + +* The `page=2&sort=Name&order=asc` portion applies to the first `QuickGrid` component. +* The `cities_sort=Country&cities_order=desc` portion applies to the second `QuickGrid` component. + +``` +?page=2&sort=Name&order=asc&cities_page=3&cities_sort=Country&cities_order=desc +``` + +:::moniker-end + +## Sort by column + +:::moniker range=">= aspnetcore-11.0" + +The `QuickGrid` component can sort items by columns. Selecting a header navigates to a URL with updated `sort` and `order` parameters. `SortByColumnAsync` navigates via `NavigationManager.NavigateTo(GetSortQueryStringUrl(...))`, so the URL always reflects the sort state. + +:::moniker-end + +:::moniker range="< aspnetcore-11.0" + +The `QuickGrid` component can sort items by columns. In Blazor Web Apps, sorting requires the component to adopt an [interactive render mode](xref:blazor/components/render-modes#render-modes). + +:::moniker-end + +Add `Sortable="true"` () to the tag: + +```razor + +``` + +In the running app, sort the QuickGrid column by selecting the rendered column title. + +:::moniker range=">= aspnetcore-11.0" + +Sort state in the URL uses the column's `Title` property as the identifier. The `sort` query parameter is set to `column.Title` (example for column title `Name`: `?sort=Name&order=asc`). On a URL change, `QuickGrid` matches the `sort` value back to a column by executing `_columns.FirstOrDefault(c => c.Title == sort.ColumnTitle)`. If no column title matches, the sort is ignored and the grid falls back to its default sort. + +Renaming a column's `Title` is a URL-breaking change. Any bookmarked or shared URLs containing the old title in the `sort` parameter stop matching, and the grid silently falls back to the default sort instead of sorting by the intended column. For `PropertyColumn`, the `Title` defaults to the property name (example: `Property="@(p => p.FirstName)"` produces `Title="First Name"`), so renaming the property or explicitly changing the `Title` parameter both break existing URLs. + > [!NOTE] -> The approach described in this section is simplified by URL-based navigation in .NET 11 or later. For more information, see this section in a .NET 11 or later version of this article. +> Using the default URL-based navigation, selectors targeting `button.col-title` must also target `a.col-title`, and `nav button`/`nav button:disabled` require `nav a`/`nav a[aria-disabled="true"]`. The built-in QuickGrid stylesheet provides both by default. + +:::moniker-end ---> +## Open and return from a details page with a paged QuickGrid component + +:::moniker range=">= aspnetcore-11.0" + +A paged QuickGrid component can open a details page for a record and return to the correct page of results using the approach in this section. URL-based navigation is used to save the page number and return the user to the same page of items from a details page. + +:::moniker-end + +:::moniker range="< aspnetcore-11.0" + +A paged QuickGrid component can open a details page for a record and return to the correct page of results using the approach in this section. + +> [!NOTE] +> The approach described in this section is simplified by URL-based navigation in .NET 11 or later. For more information, see this section in a .NET 11 or later version of this article. The following API is used: * : Gets the current zero-based page index. * : Sets the current page index and notifies any associated `QuickGrid` components to fetch and render updated data. - - The `Details` component receives the page number from the query string in the `Page` property and uses it to form a link back to the `QuickGrid` component at `/scifi-characters`. `Details.razor`: @@ -199,10 +353,6 @@ The `Details` component receives the page number from the query string in the `P The `SciFiCharacters` component: - - * Pages the `QuickGrid` component by calling on component initialization, setting the page index with the value of `Page` (page number) minus one (`-1`). The `page` query string parameter is removed after setting the page index using and [`GetUriWithQueryParameter`](xref:blazor/fundamentals/navigation#query-strings). * Opens the preceding `Details` component with the current page number, the page index incremented by one (`+1`), to make the value a one-based index () in the query string. A one-based index for the `page` query string parameter matches the rendered `Paginator` component's rendered one-based page number in the UI. @@ -336,12 +484,8 @@ In `Details.razor`: } ``` - - ## Apply row styles Apply styles to rows using [CSS isolation](xref:blazor/components/css-isolation), which can include styling empty rows for `QuickGrid` components that [page data with a `Paginator` component](#page-items-with-a-paginator-component). diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md b/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md index 13c0603ada16..b854e1068e45 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md @@ -210,3 +210,105 @@ Two trimming changes shrink published Blazor WebAssembly apps that don't use [Op * `HotReloadManager` now exposes a feature-switched `IsSupported` property tied to `System.Reflection.Metadata.MetadataUpdater.IsSupported`, so the trimmer can eliminate hot-reload caches and metadata-update handler registrations across the renderer when published [[blazor][wasm] Fix hot reload IL trimming (`dotnet/aspnetcore` #65903)](https://github.com/dotnet/aspnetcore/pull/65903) (Please don't comment on closed issues and PRs). Apps that use OTEL or Hot Reload aren't affected by the preceding updates. + + From 209d364556526f2b6516814423339800cd60a7e7 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Fri, 29 May 2026 11:27:37 -0400 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- aspnetcore/blazor/components/quickgrid.md | 2 +- aspnetcore/release-notes/aspnetcore-11/includes/blazor.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/components/quickgrid.md b/aspnetcore/blazor/components/quickgrid.md index 50aa4e28b86e..d0b0be21ce79 100644 --- a/aspnetcore/blazor/components/quickgrid.md +++ b/aspnetcore/blazor/components/quickgrid.md @@ -355,7 +355,7 @@ The `SciFiCharacters` component: :::moniker range=">= aspnetcore-11.0" -* Automatically pages the `QuickGrid` component on component initialization using [URL-based navigation](#url-based-navigation), which sets the page index from the value of a `page` query string value, if it exists. +* Automatically pages the `QuickGrid` component on component initialization using [URL-based navigation](#pagination-modes), which sets the page index from the value of a `page` query string value, if it exists. * Opens the preceding `Details` component with the current page number, the current page index incremented by one (`+1`), to make the value a one-based index () in the query string. A one-based index for the `page` query string parameter matches the rendered `Paginator` component's rendered one-based page number in the UI. `ScifiCharacters.razor`: diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md b/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md index b854e1068e45..9219ab5184ff 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/blazor.md @@ -259,7 +259,7 @@ In releases prior to .NET 11, the following `QuickGrid` components worked implic ``` -With the release of .NET 11, the following `QuickGrid` components require unique a `QueryParameterNamePrefix`. The first `QuickGrid` uses the default empty string prefix, while the second one sets `cities` as the prefix: +With the release of .NET 11, the following `QuickGrid` components require a unique `QueryParameterNamePrefix`. The first `QuickGrid` uses the default empty string prefix, while the second one sets `cities` as the prefix: ```razor