Compartir a través de


Componentes BlazorQuickGrid de ASP.NET Core

El componente QuickGrid es un componente Razor para mostrar datos de forma rápida y eficaz en formato tabular. QuickGrid proporciona un componente de la cuadrícula de datos que resulta conveniente y simple para escenarios de representación de cuadrículas comunes y sirve de arquitectura de referencia y línea de base de rendimiento para crear componentes de cuadrícula de datos. QuickGrid está altamente optimizado y usa técnicas avanzadas para lograr un rendimiento óptimo de representación.

Paquete

Agregue una referencia de paquete para el paquete Microsoft.AspNetCore.Components.QuickGrid.

Nota:

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Aplicación de ejemplo

Para ver varias demostraciones de QuickGrid, consulte QuickGrid para la Blazor aplicación de ejemplo. El sitio de demostración se hospeda en GitHub Pages. El sitio se carga rápidamente gracias a la representación previa estática mediante el proyecto de GitHub BlazorWasmPrerendering.Build mantenido por la comunidad.

Implementación de QuickGrid

Para implementar un componente QuickGrid:

  • Especifique etiquetas para el componente QuickGrid en el marcado Razor (<QuickGrid>...</QuickGrid>).
  • Asigne un nombre a un origen de datos consultable para la cuadrícula. Use cualquiera de los siguientes orígenes de datos:
    • Items: IQueryable<TGridItem> que admite un valor NULL, donde TGridItem es el tipo de datos representado por cada fila de la cuadrícula.
    • ItemsProvider: devolución de llamada que proporciona datos para la cuadrícula.
  • Class: un nombre de clase CSS opcional. Si se proporciona, el nombre de clase se incluye en el atributo class de la tabla representada.
  • Theme: un nombre de tema (valor predeterminado: default). Esto afecta a las reglas de estilo que coinciden con la tabla.
  • Virtualize: si es true, la cuadrícula se representa con virtualización. Esta acción se lleva a cabo normalmente junto con el desplazamiento y hace que la cuadrícula capture y represente solo los datos alrededor de la ventanilla de desplazamiento actual. Esto puede hacer que el rendimiento mejore considerablemente al desplazarse por grandes conjuntos de datos. Si usa Virtualize, debe proporcionar un valor para ItemSize y debe asegurarse de que cada fila se representa con un alto constante. Por lo general, es preferible no usar Virtualize si la cantidad de datos representados es pequeña o si usa paginación.
  • ItemSize: solo es aplicable cuando se usa Virtualize. ItemSize define un alto esperado en píxeles para cada fila, lo que permite que el mecanismo de virtualización capture el número correcto de elementos para que coincida con el tamaño de pantalla y para garantizar un desplazamiento preciso.
  • ItemKey: define opcionalmente un valor para @key en cada fila representada. Normalmente, se usa para especificar un identificador único, como un valor de clave principal, para cada elemento de datos. Esto permite que la cuadrícula conserve la asociación entre elementos de fila y elementos de datos en función de sus identificadores únicos, incluso cuando las instancias TGridItem se reemplazan por nuevas copias (por ejemplo, después de una nueva consulta en el almacén de datos subyacente). Si no se establece, @key es la instancia de TGridItem.
  • OverscanCount: define el número de elementos adicionales que se van a representar antes y después de la región visible para reducir la frecuencia de representación durante el desplazamiento. Aunque los valores más altos pueden mejorar la suavidad del desplazamiento representando más elementos fuera de pantalla, un valor mayor también puede dar lugar a un aumento en los tiempos de carga iniciales. Se recomienda encontrar un equilibrio en función del tamaño del conjunto de datos y los requisitos de experiencia del usuario. El valor predeterminado es 3. Solo disponible al usar Virtualize.
  • Pagination: opcionalmente vincula esta instancia TGridItem con un modelo PaginationState, lo que hace que la cuadrícula capture y represente solo la página actual de datos. Normalmente se usa junto con un componente Paginator o con alguna otra lógica de interfaz de usuario que muestra y actualiza la instancia PaginationState proporcionada.
  • En el contenido secundario QuickGrid (RenderFragment), especifique PropertyColumn<TGridItem,TProp>, que representan columnas TGridItem cuyas celdas muestran valores:
    • Property: define el valor que se va a mostrar en las celdas de esta columna.
    • Format: opcionalmente especifica una cadena de formato para el valor. El uso de Format requiere que el tipo TProp implemente IFormattable.
    • Sortable: indica si esta columna debe poder ordenar los datos. El valor predeterminado puede variar según el tipo de columna. Por ejemplo, se puede ordenar TemplateColumn<TGridItem> de forma predeterminada si se especifica algún parámetro SortBy.
    • InitialSortDirection: indica la dirección de ordenación si IsDefaultSortColumn es true.
    • IsDefaultSortColumn: indica si esta columna debe ordenarse de forma predeterminada.
    • PlaceholderTemplate: si se especifica, las cuadrículas virtualizadas usan esta plantilla para representar celdas cuyos datos no se han cargado.
    • HeaderTemplate: plantilla opcional para la celda de encabezado de esta columna. Si no se especifica, la plantilla de encabezado predeterminada incluye el Title, junto con los indicadores de ordenación y los botones de opciones aplicables.
    • Title: texto del título de la columna. El título se representa automáticamente si no se usa HeaderTemplate.
  • Especifique etiquetas para el componente QuickGrid en el marcado Razor (<QuickGrid>...</QuickGrid>).
  • Asigne un nombre a un origen de datos consultable para la cuadrícula. Use cualquiera de los siguientes orígenes de datos:
    • Items: IQueryable<TGridItem> que admite un valor NULL, donde TGridItem es el tipo de datos representado por cada fila de la cuadrícula.
    • ItemsProvider: devolución de llamada que proporciona datos para la cuadrícula.
  • Class: un nombre de clase CSS opcional. Si se proporciona, el nombre de clase se incluye en el atributo class de la tabla representada.
  • Theme: un nombre de tema (valor predeterminado: default). Esto afecta a las reglas de estilo que coinciden con la tabla.
  • Virtualize: si es true, la cuadrícula se representa con virtualización. Esta acción se lleva a cabo normalmente junto con el desplazamiento y hace que la cuadrícula capture y represente solo los datos alrededor de la ventanilla de desplazamiento actual. Esto puede hacer que el rendimiento mejore considerablemente al desplazarse por grandes conjuntos de datos. Si usa Virtualize, debe proporcionar un valor para ItemSize y debe asegurarse de que cada fila se representa con un alto constante. Por lo general, es preferible no usar Virtualize si la cantidad de datos representados es pequeña o si usa paginación.
  • ItemSize: solo es aplicable cuando se usa Virtualize. ItemSize define un alto esperado en píxeles para cada fila, lo que permite que el mecanismo de virtualización capture el número correcto de elementos para que coincida con el tamaño de pantalla y para garantizar un desplazamiento preciso.
  • ItemKey: define opcionalmente un valor para @key en cada fila representada. Normalmente, se usa para especificar un identificador único, como un valor de clave principal, para cada elemento de datos. Esto permite que la cuadrícula conserve la asociación entre elementos de fila y elementos de datos en función de sus identificadores únicos, incluso cuando las instancias TGridItem se reemplazan por nuevas copias (por ejemplo, después de una nueva consulta en el almacén de datos subyacente). Si no se establece, @key es la instancia de TGridItem.
  • Pagination: opcionalmente vincula esta instancia TGridItem con un modelo PaginationState, lo que hace que la cuadrícula capture y represente solo la página actual de datos. Normalmente se usa junto con un componente Paginator o con alguna otra lógica de interfaz de usuario que muestra y actualiza la instancia PaginationState proporcionada.
  • En el contenido secundario QuickGrid (RenderFragment), especifique PropertyColumn<TGridItem,TProp>, que representan columnas TGridItem cuyas celdas muestran valores:
    • Property: define el valor que se va a mostrar en las celdas de esta columna.
    • Format: opcionalmente especifica una cadena de formato para el valor. El uso de Format requiere que el tipo TProp implemente IFormattable.
    • Sortable: indica si esta columna debe poder ordenar los datos. El valor predeterminado puede variar según el tipo de columna. Por ejemplo, se puede ordenar TemplateColumn<TGridItem> de forma predeterminada si se especifica algún parámetro SortBy.
    • InitialSortDirection: indica la dirección de ordenación si IsDefaultSortColumn es true.
    • IsDefaultSortColumn: indica si esta columna debe ordenarse de forma predeterminada.
    • PlaceholderTemplate: si se especifica, las cuadrículas virtualizadas usan esta plantilla para representar celdas cuyos datos no se han cargado.
    • HeaderTemplate: plantilla opcional para la celda de encabezado de esta columna. Si no se especifica, la plantilla de encabezado predeterminada incluye el Title, junto con los indicadores de ordenación y los botones de opciones aplicables.
    • Title: texto del título de la columna. El título se representa automáticamente si no se usa HeaderTemplate.

Por ejemplo, agregue el siguiente componente para representar una cuadrícula.

Para Blazor Web Apps, el componente QuickGrid debe adoptar un modo de representación interactivo para habilitar características interactivas, como la paginación y la ordenación.

PromotionGrid.razor:

@page "/promotion-grid"
@using Microsoft.AspNetCore.Components.QuickGrid

<PageTitle>Promotion Grid</PageTitle>

<h1>Promotion Grid Example</h1>

<QuickGrid Items="people">
    <PropertyColumn Property="@(p => p.PersonId)" Sortable="true" />
    <PropertyColumn Property="@(p => p.Name)" Sortable="true" />
    <PropertyColumn Property="@(p => p.PromotionDate)" Format="yyyy-MM-dd" Sortable="true" />
</QuickGrid>

@code {
    private record Person(int PersonId, string Name, DateOnly PromotionDate);

    private IQueryable<Person> people = new[]
    {
        new Person(10895, "Jean Martin", new DateOnly(1985, 3, 16)),
        new Person(10944, "António Langa", new DateOnly(1991, 12, 1)),
        new Person(11203, "Julie Smith", new DateOnly(1958, 10, 10)),
        new Person(11205, "Nur Sari", new DateOnly(1922, 4, 27)),
        new Person(11898, "Jose Hernandez", new DateOnly(2011, 5, 3)),
        new Person(12130, "Kenji Sato", new DateOnly(2004, 1, 9)),
    }.AsQueryable();
}

Acceda al componente en un explorador en la ruta de acceso relativa /promotion-grid.

En este momento, no se prevén ampliaciones de QuickGrid con características que las cuadrículas comerciales totalmente desarrolladas tienden a ofrecer, por ejemplo: filas jerárquicas, columnas que se pueden arrastrar para reorganizar o selecciones de intervalos similares a Excel. Si necesita características avanzadas que no desea desarrollar por su cuenta, siga usando cuadrículas de terceros.

Ordenar por columna

El componente QuickGrid puede ordenar los elementos por columnas. En Blazor Web Apps, la ordenación requiere que el componente adopte un modo de representación interactivo.

Agregue Sortable="true" (Sortable) a la etiqueta PropertyColumn<TGridItem,TProp>:

<PropertyColumn Property="..." Sortable="true" />

En la aplicación en ejecución, ordene la columna QuickGrid seleccionando el título de la columna representada.

Elementos de página con un componente Paginator

El componente QuickGrid puede paginar datos del origen de datos. En Blazor Web Apps, la paginación requiere que el componente adopte un modo de representación interactivo.

Agregue una instancia PaginationState al bloque @code del componente. Establezca el ItemsPerPage en el número de elementos que se van a mostrar por página. En el ejemplo siguiente, la instancia se denomina pagination y se establecen diez elementos por página:

PaginationState pagination = new PaginationState { ItemsPerPage = 10 };

Establezca la propiedad Pagination del componente QuickGrid en pagination:

<QuickGrid Items="..." Pagination="pagination">

Para proporcionar una interfaz de usuario para la paginación, agregue un componente Paginatorencima, debajo, o tanto encima como debajo del componente QuickGrid. Establezca el Paginator.State en pagination:

<Paginator State="pagination" />

En la aplicación en ejecución, navegue por los elementos mediante un componente Paginator representado.

Atributos y estilos personalizados

QuickGrid también admite el paso de atributos personalizados y clases de estilo (Class) al elemento de tabla representado:

<QuickGrid Items="..." custom-attribute="value" Class="custom-class">

Origen de datos de Entity Framework Core (EF Core)

Use el patrón de fábrica para resolver un contexto de base de datos de EF Core que proporciona datos a un componente de QuickGrid. Para obtener más información sobre por qué se recomienda el patrón de fábrica, vea ASP.NET Core Blazor con Entity Framework Core (EF Core).

Un generador de contextos de base de datos (IDbContextFactory<TContext>) se inserta en el componente con la directiva @inject. El enfoque de fábrica requiere la eliminación del contexto de la base de datos, por lo que el componente implementa la interfaz IAsyncDisposable con la directiva @implements. El proveedor de elementos del componente QuickGrid es un DbSet<T> obtenido del contexto de base de datos creado (CreateDbContext) del generador de contexto de base de datos insertado.

QuickGrid reconoce las instancias de IQueryable proporcionadas por EF y sabe cómo resolver consultas de forma asincrónica para lograr una eficacia.

Agregue una referencia de paquete para el Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapterpaquete NuGet.

Nota:

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Llame a AddQuickGridEntityFrameworkAdapter en la colección de servicios en el archivo Program para registrar una implementación de IAsyncQueryExecutor compatible con EF:

builder.Services.AddQuickGridEntityFrameworkAdapter();

En el ejemplo siguiente se usa un ExampleTable DbSet<TEntity> (tabla) de un contexto de base de datos de AppDbContext (context) como origen de datos para un componente de QuickGrid:

@using Microsoft.AspNetCore.Components.QuickGrid
@using Microsoft.EntityFrameworkCore
@implements IAsyncDisposable
@inject IDbContextFactory<AppDbContext> DbFactory

...

<QuickGrid ... Items="context.ExampleTable" ...>
    ...
</QuickGrid>

@code {
    private AppDbContext context = default!;

    protected override void OnInitialized()
    {
        context = DbFactory.CreateDbContext();
    }

    public async ValueTask DisposeAsync() => await context.DisposeAsync();
}

En el bloque de código (@code) del ejemplo anterior:

  • El campo context contiene el contexto de la base de datos, escrito como un AppDbContext.
  • El método de ciclo de vida de OnInitialized asigna un nuevo contexto de base de datos (CreateDbContext) al campo context del generador insertado (DbFactory).
  • El método asincrónico DisposeAsync elimina el contexto de la base de datos cuando se elimina el componente.

También puede usar cualquier operador LINQ compatible con EF para filtrar los datos antes de pasarlos al parámetro Items.

En el ejemplo siguiente se filtran las películas por un título de película escrito en un cuadro de búsqueda. El contexto de la base de datos es BlazorWebAppMoviesContext, y el modelo es Movie. La propiedad Title de la película se usa para la operación de filtro.

@using Microsoft.AspNetCore.Components.QuickGrid
@using Microsoft.EntityFrameworkCore
@implements IAsyncDisposable
@inject IDbContextFactory<BlazorWebAppMoviesContext> DbFactory

...

<p>
    <input type="search" @bind="titleFilter" @bind:event="oninput" />
</p>

<QuickGrid ... Items="FilteredMovies" ...>
    ...
</QuickGrid>

@code {
    private string titleFilter = string.Empty;
    private BlazorWebAppMoviesContext context = default!;

    protected override void OnInitialized()
    {
        context = DbFactory.CreateDbContext();
    }

    private IQueryable<Movie> FilteredMovies => 
        context.Movie.Where(m => m.Title!.Contains(titleFilter));

    public async ValueTask DisposeAsync() => await context.DisposeAsync();
}

Compatibilidad con nombres para mostrar

Se puede asignar un título de columna mediante ColumnBase<TGridItem>.Title en la etiqueta de PropertyColumn<TGridItem,TProp>. En el ejemplo de película siguiente, a la columna se le asigna el nombre "Release Date" para los datos de fecha de lanzamiento de películas de la columna:

<PropertyColumn Property="movie => movie.ReleaseDate" Title="Release Date" />

Sin embargo, la administración de títulos de columna (nombres) de las propiedades del modelo enlazadas suele ser una mejor opción para mantener una aplicación. Un modelo puede controlar el nombre para mostrar de una propiedad con el atributo [Display]. En el siguiente ejemplo, el modelo especifica un nombre para mostrar de fecha de lanzamiento de película de "Release Date" para su propiedad ReleaseDate:

[Display(Name = "Release Date")]
public DateTime ReleaseDate { get; set; }

Para permitir que el componente QuickGrid use el DisplayAttribute.Name, la subclase PropertyColumn<TGridItem,TProp> en el componente o en una clase independiente:

public class DisplayNameColumn<TGridItem, TProp> : PropertyColumn<TGridItem, TProp>
{
    protected override void OnParametersSet()
    {
        if (Title is null && Property.Body is MemberExpression memberExpression)
        {
            var memberInfo = memberExpression.Member;
            Title = 
                memberInfo.GetCustomAttribute<DisplayNameAttribute>().DisplayName ??
                memberInfo.GetCustomAttribute<DisplayAttribute>().Name ??
                memberInfo.Name;
        }

        base.OnParametersSet();
    }
}

Use la subclase en el componente QuickGrid. En el siguiente ejemplo, se usa el DisplayNameColumn anterior. El nombre "Release Date" lo proporciona el atributo [Display] en el modelo, por lo que no es necesario especificar un Title:

<DisplayNameColumn Property="movie => movie.ReleaseDate" />

El atributo [DisplayName] se admite:

[DisplayName("Release Date")]
public DateTime ReleaseDate { get; set; }

Sin embargo, se recomienda el atributo [Display] porque hace que haya propiedades adicionales disponibles. Por ejemplo, el atributo [Display] ofrece la capacidad de asignar un tipo de recurso para la localización.

Datos remotos

En aplicaciones Blazor WebAssembly, capturar datos de una API web basada en JSON en un servidor es un requisito común. Para capturar solo los datos necesarios para la página o ventanilla actuales de los datos y aplicar reglas de ordenación o filtrado en el servidor, use el parámetro ItemsProvider.

ItemsProvider también se puede usar en una aplicación de Blazor del lado servidor si la aplicación es necesaria para consultar un punto de conexión externo o en otros casos en los que un IQueryable no cubre los requisitos.

Proporcione una devolución de llamada que coincida con el tipo de delegado GridItemsProvider<TGridItem>, donde TGridItem es el tipo de datos que se muestran en la cuadrícula. La devolución de llamada recibe un parámetro de tipo GridItemsProviderRequest<TGridItem>, que especifica el índice de inicio, el número máximo de filas y el orden de ordenación de los datos que se van a devolver. Además de devolver los elementos coincidentes, también se requiere un recuento total de elementos (totalItemCount) para que la paginación y la virtualización funcionen correctamente.

En el ejemplo siguiente se obtienen datos de la base de datos pública OpenFDA Food Enforcement.

El GridItemsProvider<TGridItem> convierte el GridItemsProviderRequest<TGridItem> en una consulta en la base de datos de OpenFDA. Los parámetros de consulta se traducen en el formato de dirección URL determinado admitido por la API JSON externa. Solo es posible realizar la ordenación y el filtrado mediante la ordenación y el filtrado admitidos por la API externa. El punto de conexión de OpenFDA no admite la ordenación, por lo que ninguna de las columnas se marca como ordenable. Sin embargo, admite la omisión de registros (parámetro skip) y la limitación del retorno de registros (parámetro limit), por lo que el componente puede habilitar la virtualización y desplazarse rápidamente a través de decenas de miles de registros.

FoodRecalls.razor:

@page "/food-recalls"
@inject HttpClient Http
@inject NavigationManager NavManager

<PageTitle>Food Recalls</PageTitle>

<h1>OpenFDA Food Recalls</h1>

<div class="grid" tabindex="-1">
    <QuickGrid ItemsProvider="@foodRecallProvider" Virtualize="true">
        <PropertyColumn Title="ID" Property="@(c => c.Event_Id)" />
        <PropertyColumn Property="@(c => c.State)" />
        <PropertyColumn Property="@(c => c.City)" />
        <PropertyColumn Title="Company" Property="@(c => c.Recalling_Firm)" />
        <PropertyColumn Property="@(c => c.Status)" />
    </QuickGrid>
</div>

<p>Total: <strong>@numResults results found</strong></p>

@code {
    GridItemsProvider<FoodRecall>? foodRecallProvider;
    int numResults;

    protected override async Task OnInitializedAsync()
    {
        foodRecallProvider = async req =>
        {
            var url = NavManager.GetUriWithQueryParameters(
                "https://api.fda.gov/food/enforcement.json", 
                new Dictionary<string, object?>
            {
                { "skip", req.StartIndex },
                { "limit", req.Count },
            });

            var response = await Http.GetFromJsonAsync<FoodRecallQueryResult>(
                url, req.CancellationToken);

            return GridItemsProviderResult.From(
                items: response!.Results,
                totalItemCount: response!.Meta.Results.Total);
        };

        numResults = (await Http.GetFromJsonAsync<FoodRecallQueryResult>(
            "https://api.fda.gov/food/enforcement.json"))!.Meta.Results.Total;
    }
}

Para obtener más información sobre cómo llamar a las API web, consulte Llamada a una API web desde una aplicación Blazor de ASP.NET Core.

Scaffolder QuickGrid

El scaffolder QuickGrid agrupa componentes Razor con QuickGrid para mostrar datos de una base de datos.

El proveedor de scaffolding genera páginas básicas de creación, lectura, actualización y eliminación (CRUD) basadas en un modelo de datos de Entity Framework Core. Puede aplicar scaffolding a páginas individuales o a todas las páginas CRUD. Seleccione la clase de modelo y DbContext, opcionalmente para crear una instancia deDbContext si es necesario.

Los componentes Razor con scaffolding se agregan a la carpeta en una carpeta generada con el mismo nombre que la clase de modelo. El componente generado Index usa un componente QuickGrid para mostrar los datos. Personalice los componentes generados según sea necesario y habilite la interactividad para sacar provecho de las características interactivas, como la paginación, la ordenación y el filtrado.

Los componentes generados por el proveedor de scaffolding necesitan la representación del lado servidor (SSR), por lo que no se admiten al ejecutarse en WebAssembly.

Haga clic con el botón derecho en la carpeta Components/Pages y seleccione Agregar>Nuevo elemento con scaffolding.

Con el cuadro de diálogo Agregar nuevo elemento de scaffolding abierto en Instalado>Común>Razor Componente, seleccione Razor Componentes mediante Entity Framework (CRUD). Seleccione el botón Agregar.

Complete el cuadro de diálogo Agregar componentes Razor mediante Entity Framework (CRUD):

  • La lista desplegable Plantilla incluye otras plantillas para crear específicamente componentes de creación, edición, eliminación, detalles y listas. Esta lista desplegable resulta útil cuando solo necesita crear un tipo específico de componente con scaffolding en una clase de modelo. Deje la lista desplegable Plantilla establecida en CRUD para aplicar scaffolding a un conjunto completo de componentes.
  • En la lista desplegable Clase de modelo, seleccione la clase de modelo. Se crea una carpeta para los componentes generados a partir del nombre del modelo (si la clase de modelo se denomina Movie, la carpeta se denomina MoviePagesautomáticamente).
  • Para la clase DbContext, seleccione un contexto de base de datos existente o seleccione el botón + (signo más) y el cuadro de diálogo modal Agregar contexto de datos para agregar un nuevo contexto de base de datos.
  • Una vez que se cierra el cuadro de diálogo del modelo, la lista desplegable Proveedor de base de datos tiene como valor predeterminado SQL Server. Puede seleccionar el proveedor adecuado para la base de datos que está usando. Las opciones incluyen SQL Server, SQLite, PostgreSQL y Azure Cosmos DB.
  • Seleccione Agregar.