Bagikan melalui


komponen ASP.NET Core BlazorQuickGrid

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 10 dari artikel ini.

Komponen QuickGrid adalah komponen Razor untuk menampilkan data dengan cepat dan efisien dalam bentuk tabular. QuickGrid menyediakan komponen kisi data yang sederhana dan nyaman untuk skenario penyajian kisi umum dan berfungsi sebagai arsitektur referensi dan garis besar performa untuk membangun komponen kisi data. QuickGrid sangat dioptimalkan dan menggunakan teknik canggih untuk mencapai performa penyajian yang optimal.

Paket

Tambahkan referensi paket untuk paket Microsoft.AspNetCore.Components.QuickGrid.

Catatan

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Aplikasi contoh

Untuk berbagai demonstrasi QuickGrid, lihat QuickGrid untuk contoh aplikasi Blazor. Situs demo dihosting di Halaman GitHub. Situs ini dimuat dengan cepat berkat prarender statis menggunakan proyek BlazorWasmPrerendering.Build GitHub yang dikelola oleh komunitas.

QuickGrid pelaksanaan

Untuk mengimplementasikan komponen QuickGrid:

  • Tentukan tag untuk QuickGrid komponen dalam Razor markup (<QuickGrid>...</QuickGrid>).
  • Sebutkan sumber data yang dapat dikueri untuk grid. Gunakan salah satu sumber data berikut:
    • Items: IQueryable<TGridItem> yang dapat bernilai null, di mana TGridItem adalah jenis data yang diwakili oleh setiap baris dalam tabel.
    • ItemsProvider: Callback yang menyediakan data untuk grid.
  • Class: Nama kelas CSS opsional. Jika disediakan, nama kelas disertakan dalam class atribut tabel yang dirender.
  • Theme: Nama tema (nilai default: default). Ini memengaruhi aturan gaya mana yang cocok dengan tabel.
  • Virtualize: Jika benar, kisi dirender dengan virtualisasi. Ini biasanya digunakan bersama pengguliran dan menyebabkan kisi hanya mengambil dan merender data yang ada di sekitar viewport gulir saat ini. Ini dapat sangat meningkatkan performa saat menggulir kumpulan data besar. Jika Anda menggunakan Virtualize, Anda harus menyediakan nilai untuk ItemSize dan harus memastikan bahwa setiap baris dirender dengan tinggi konstan. Umumnya, lebih baik tidak digunakan Virtualize jika jumlah data yang dirender kecil atau jika Anda menggunakan penomoran halaman.
  • ItemSize: Hanya berlaku saat menggunakan Virtualize. ItemSize menentukan tinggi yang diharapkan dalam piksel untuk setiap baris, memungkinkan mekanisme virtualisasi untuk mengambil jumlah item yang benar agar sesuai dengan ukuran tampilan dan untuk memastikan pengguliran yang akurat.
  • ItemKey: Secara opsional mendefinisikan nilai untuk @key pada setiap baris yang dirender. Biasanya, ini digunakan untuk menentukan pengidentifikasi unik, seperti nilai kunci utama, untuk setiap item data. Ini memungkinkan kisi untuk mempertahankan hubungan antara elemen baris dan item data berdasarkan pengidentifikasi uniknya, bahkan ketika TGridItem instans digantikan oleh salinan baru (misalnya, setelah kueri baru terhadap penyimpanan data yang mendasarinya). Jika tidak diatur, @key adalah instansi TGridItem.
  • OverscanCount: Menentukan berapa banyak item tambahan yang akan dirender sebelum dan sesudah wilayah yang terlihat untuk mengurangi frekuensi penyajian selama pengguliran. Meskipun nilai yang lebih tinggi dapat meningkatkan kehalusan gulir dengan merender lebih banyak item di luar layar, nilai yang lebih tinggi juga dapat mengakibatkan peningkatan waktu muat awal. Direkomendasikan untuk menemukan keseimbangan berdasarkan ukuran himpunan data dan persyaratan pengalaman pengguna Anda. Nilai defaultnya adalah 3. Hanya tersedia saat menggunakan Virtualize.
  • Pagination: Secara opsional, menautkan instans TGridItem ini dengan model PaginationState, sehingga grid hanya mengambil dan merender halaman data saat ini saja. Ini biasanya digunakan bersama dengan Paginator komponen atau beberapa logika UI lain yang menampilkan dan memperbarui instans yang disediakan PaginationState .
  • Dalam konten anak (QuickGrid), tentukan RenderFragment, yang mewakili kolom PropertyColumn<TGridItem,TProp> yang selnya menampilkan nilai:
    • Property: Menentukan nilai yang akan ditampilkan dalam sel kolom ini.
    • Format: Secara opsional menentukan string format untuk nilai . Menggunakan Format memerlukan jenis TProp untuk mengimplementasikan IFormattable.
    • Sortable: Menunjukkan apakah data harus dapat diurutkan berdasarkan kolom ini. Nilai default dapat bervariasi sesuai dengan jenis kolom. Misalnya, TemplateColumn<TGridItem> diurutkan jika parameter SortBy telah ditentukan.
    • InitialSortDirection: Menunjukkan arah pengurutan jika IsDefaultSortColumn adalah true.
    • IsDefaultSortColumn: Menunjukkan apakah kolom ini harus diurutkan secara default.
    • PlaceholderTemplate: Jika disediakan, grid virtual menggunakan templat ini untuk merender sel yang datanya belum dimuat.
    • HeaderTemplate: Templat opsional untuk sel header kolom ini. Jika tidak ditentukan, templat header default menyertakan Title, bersama dengan indikator pengurutan dan tombol opsi yang berlaku.
    • Title: Teks judul untuk kolom. Judul dirender secara otomatis jika HeaderTemplate tidak digunakan.
  • Tentukan tag untuk QuickGrid komponen dalam Razor markup (<QuickGrid>...</QuickGrid>).
  • Sebutkan sumber data yang dapat dikueri untuk grid. Gunakan salah satu sumber data berikut:
    • Items: IQueryable<TGridItem> yang dapat bernilai null, di mana TGridItem adalah jenis data yang diwakili oleh setiap baris dalam tabel.
    • ItemsProvider: Callback yang menyediakan data untuk grid.
  • Class: Nama kelas CSS opsional. Jika disediakan, nama kelas disertakan dalam class atribut tabel yang dirender.
  • Theme: Nama tema (nilai default: default). Ini memengaruhi aturan gaya mana yang cocok dengan tabel.
  • Virtualize: Jika benar, kisi dirender dengan virtualisasi. Ini biasanya digunakan bersama pengguliran dan menyebabkan kisi hanya mengambil dan merender data yang ada di sekitar viewport gulir saat ini. Ini dapat sangat meningkatkan performa saat menggulir kumpulan data besar. Jika Anda menggunakan Virtualize, Anda harus menyediakan nilai untuk ItemSize dan harus memastikan bahwa setiap baris dirender dengan tinggi konstan. Umumnya, lebih baik tidak digunakan Virtualize jika jumlah data yang dirender kecil atau jika Anda menggunakan penomoran halaman.
  • ItemSize: Hanya berlaku saat menggunakan Virtualize. ItemSize menentukan tinggi yang diharapkan dalam piksel untuk setiap baris, memungkinkan mekanisme virtualisasi untuk mengambil jumlah item yang benar agar sesuai dengan ukuran tampilan dan untuk memastikan pengguliran yang akurat.
  • ItemKey: Secara opsional mendefinisikan nilai untuk @key pada setiap baris yang dirender. Biasanya, ini digunakan untuk menentukan pengidentifikasi unik, seperti nilai kunci utama, untuk setiap item data. Ini memungkinkan kisi untuk mempertahankan hubungan antara elemen baris dan item data berdasarkan pengidentifikasi uniknya, bahkan ketika TGridItem instans digantikan oleh salinan baru (misalnya, setelah kueri baru terhadap penyimpanan data yang mendasarinya). Jika tidak diatur, @key adalah instansi TGridItem.
  • Pagination: Secara opsional, menautkan instans TGridItem ini dengan model PaginationState, sehingga grid hanya mengambil dan merender halaman data saat ini saja. Ini biasanya digunakan bersama dengan Paginator komponen atau beberapa logika UI lain yang menampilkan dan memperbarui instans yang disediakan PaginationState .
  • Dalam konten anak (QuickGrid), tentukan RenderFragment, yang mewakili kolom PropertyColumn<TGridItem,TProp> yang selnya menampilkan nilai:
    • Property: Menentukan nilai yang akan ditampilkan dalam sel kolom ini.
    • Format: Secara opsional menentukan string format untuk nilai . Menggunakan Format memerlukan jenis TProp untuk mengimplementasikan IFormattable.
    • Sortable: Menunjukkan apakah data harus dapat diurutkan berdasarkan kolom ini. Nilai default dapat bervariasi sesuai dengan jenis kolom. Misalnya, TemplateColumn<TGridItem> diurutkan jika parameter SortBy telah ditentukan.
    • InitialSortDirection: Menunjukkan arah pengurutan jika IsDefaultSortColumn adalah true.
    • IsDefaultSortColumn: Menunjukkan apakah kolom ini harus diurutkan secara default.
    • PlaceholderTemplate: Jika disediakan, grid virtual menggunakan templat ini untuk merender sel yang datanya belum dimuat.
    • HeaderTemplate: Templat opsional untuk sel header kolom ini. Jika tidak ditentukan, templat header default menyertakan Title, bersama dengan indikator pengurutan dan tombol opsi yang berlaku.
    • Title: Teks judul untuk kolom. Judul dirender secara otomatis jika HeaderTemplate tidak digunakan.

Misalnya, tambahkan komponen berikut untuk merender kisi.

Untuk Blazor Web Apps, komponen QuickGrid harus mengadopsi mode render interaktif untuk memungkinkan fitur interaktif, seperti penomoran dan pengurutan.

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();
}
@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();
}

Akses komponen di browser pada jalur relatif /promotion-grid.

Tidak ada rencana saat ini untuk memperluas QuickGrid dengan fitur yang biasanya ditawarkan oleh grid komersial sepenuhnya, misalnya, baris hierarkis, seret untuk mengurutkan ulang kolom, atau pemilihan rentang ala Excel. Jika Anda memerlukan fitur lanjutan yang tidak ingin Anda kembangkan sendiri, lanjutkan menggunakan kisi pihak ketiga.

Urutkan berdasarkan kolom

Komponen QuickGrid dapat mengurutkan item menurut kolom. Dalam Blazor Web Apps, pengurutan memerlukan komponen untuk mengadopsi mode interaktif render.

Tambahkan Sortable="true" (Sortable) ke PropertyColumn<TGridItem,TProp> tag:

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

Di aplikasi yang sedang berjalan, urutkan QuickGrid kolom dengan memilih judul kolom yang dirender.

Elemen halaman dengan komponen Paginator

Komponen QuickGrid dapat melakukan paging pada data dari sumber data. Dalam Blazor Web App itu, paging memerlukan komponen untuk mengadopsi mode render interaktif.

PaginationState Tambahkan instans ke blok komponen@code. Atur ItemsPerPage ke jumlah item yang akan ditampilkan per halaman. Dalam contoh berikut, instans diberi nama pagination, dan sepuluh item per halaman diatur:

PaginationState pagination = new PaginationState { ItemsPerPage = 10 };

Atur properti QuickGrid dari komponen Pagination ke pagination.

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

Untuk menyediakan UI untuk penomoran halaman, tambahkan komponen di atas atau di bawah komponen . Atur Paginator.State ke pagination:

<Paginator State="pagination" />

Di aplikasi berjalan, gulir melalui item menggunakan komponen Paginator yang dirender.

QuickGrid merender baris kosong tambahan untuk mengisi halaman akhir data saat digunakan dengan komponen Paginator. Di .NET 9 atau yang lebih baru, sel data kosong (<td></td>) ditambahkan ke baris kosong. Baris kosong dimaksudkan untuk memfasilitasi penyajian QuickGrid dengan tinggi dan gaya baris yang stabil di semua halaman.

Menerapkan gaya pada baris

Terapkan gaya pada baris-baris menggunakan isolasi CSS , yang dapat mencakup gaya untuk baris kosong pada komponen QuickGrid yang data halaman dengan komponen Paginator.

Bungkus komponen QuickGrid dalam elemen blok pembungkus, misalnya <div>:

+ <div>
    <QuickGrid ...>
        ...
    </QuickGrid>
+ </div>

Terapkan gaya baris dengan elemen pseudo ::deep. Dalam contoh berikut, tinggi baris diatur ke 2em, termasuk untuk baris data kosong.

{COMPONENT}.razor.css:

::deep tr {
    height: 2em;
}

Atau, gunakan pendekatan gaya CSS berikut:

  • Tampilkan sel baris yang diisi dengan data.
  • Jangan tampilkan sel baris kosong, untuk menghindari tampilan batas sel kosong sesuai dengan gaya Bootstrap.

{COMPONENT}.razor.css:

::deep tr:has(> td:not(:empty)) > td {
    display: table-cell;
}

::deep td:empty {
    display: none;
}

Untuk informasi selengkapnya tentang menggunakan ::deeppseudo-elemen dengan isolasi CSS, lihat ASP.NET Core Blazor isolasi CSS.

Atribut dan gaya kustom

QuickGrid juga mendukung meneruskan atribut kustom dan kelas gaya (Class) ke elemen tabel yang dirender:

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

Mengatur gaya baris tabel berdasarkan elemen pada baris

Terapkan kelas CSS pada baris kisi berdasarkan item baris dengan menggunakan parameter RowClass.

Dalam contoh berikut:

  • Item baris diwakili oleh rekaman Person. Catatan Person menyertakan properti FirstName.
  • Metode GetRowCssClass menerapkan gaya kelas highlight-row ke baris mana pun di mana nama depan orang tersebut adalah "Julie."
<QuickGrid ... RowClass="GetRowCssClass">
    ...
</QuickGrid>

@code {
    private record Person(int PersonId, string FirstName, string LastName);

    private string GetRowCssClass(Person person) =>
        person.FirstName == "Julie" ? "highlight-row" : null;
}

Tutup opsi kolom QuickGrid

Tutup UI opsi kolom QuickGrid dengan metode HideColumnOptionsAsync.

Contoh berikut menutup antarmuka pengguna opsi kolom segera setelah filter judul diterapkan:

<QuickGrid @ref="movieGrid" Items="movies">
    <PropertyColumn Property="@(m => m.Title)" Title="Title">
        <ColumnOptions>
            <input type="search" @bind="titleFilter" placeholder="Filter by title" 
                @bind:after="@(() => movieGrid.HideColumnOptionsAsync())" />
        </ColumnOptions>
    </PropertyColumn>
    <PropertyColumn Property="@(m => m.Genre)" Title="Genre" />
    <PropertyColumn Property="@(m => m.ReleaseYear)" Title="Release Year" />
</QuickGrid>

@code {
    private QuickGrid<Movie>? movieGrid;
    private string titleFilter = string.Empty;
    private IQueryable<Movie> movies = new List<Movie> { ... }.AsQueryable();
    private IQueryable<Movie> filteredMovies => 
        movies.Where(m => m.Title!.Contains(titleFilter));
}

Sumber data dari Entity Framework Core (EF Core)

Gunakan pola pabrik untuk memecahkan konteks database EF Core yang menyediakan data untuk komponen QuickGrid. Untuk informasi selengkapnya tentang mengapa pola pabrik direkomendasikan, lihat ASP.NET Core Blazor dengan Entity Framework Core (EF Core).

Pabrik konteks basis data (IDbContextFactory<TContext>) disuntikkan ke komponen menggunakan direktif @inject. Pendekatan pabrik memerlukan pembuangan konteks database, sehingga komponen mengimplementasikan IAsyncDisposable antarmuka dengan direktif @implements . Penyedia item untuk komponen QuickGrid adalah DbSet<T> yang diperoleh dari konteks database yang dibuat (CreateDbContext) oleh pabrik konteks database yang disuntikkan.

QuickGrid mengenali instans IQueryable yang disediakan EF dan tahu cara menyelesaikan kueri secara asinkron untuk efisiensi.

Tambahkan referensi untuk paket NuGet .

Catatan

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Panggil AddQuickGridEntityFrameworkAdapter pada koleksi layanan di file Program untuk mendaftarkan implementasi yang mendukung IAsyncQueryExecutor EF.

builder.Services.AddQuickGridEntityFrameworkAdapter();

Contoh berikut menggunakan ExampleTableDbSet<TEntity> (tabel) dari AppDbContext konteks database (context) sebagai sumber data untuk QuickGrid komponen:

@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();
}

Di blok kode (@code) dari contoh sebelumnya:

  • Bidang context menyimpan konteks database, ditik sebagai AppDbContext.
  • Metode siklus hidup OnInitialized menetapkan konteks basis data baru (CreateDbContext) ke field context dari factory yang diinjeksikan (DbFactory).
  • Metode asinkron DisposeAsync membuang konteks database saat komponen dibuang.

Anda juga dapat menggunakan operator LINQ yang didukung EF untuk memfilter data sebelum meneruskannya ke Items parameter .

Contoh berikut memfilter film menurut judul film yang dimasukkan dalam kotak pencarian. Konteks database adalah BlazorWebAppMoviesContext, dan modelnya adalah Movie. Properti dari film Title digunakan untuk operasi filter.

@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();
}

Untuk contoh kerja, lihat sumber daya berikut ini:

Dukungan nama tampilan

Judul kolom dapat ditetapkan menggunakan ColumnBase<TGridItem>.Title di PropertyColumn<TGridItem,TProp>tag . Dalam contoh film berikut, kolom diberi nama "Release Date" untuk data tanggal rilis film kolom:

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

Namun, mengelola judul kolom (nama) dari properti model terikat biasanya merupakan pilihan yang lebih baik untuk memelihara aplikasi. Model dapat mengontrol nama tampilan properti dengan [Display] atribut . Dalam contoh berikut, model menentukan nama tampilan tanggal rilis film "Release Date" untuk propertinya ReleaseDate :

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

Untuk mengaktifkan komponen QuickGrid agar dapat menggunakan properti DisplayAttribute.Name, buat subkelas dari PropertyColumn<TGridItem,TProp>, baik di dalam komponen maupun di dalam kelas terpisah. Panggil metode GetName untuk mengembalikan nilai DisplayAttribute.Name yang dilokalkan jika atribut DisplayName yang tidak dilokalkan ([DisplayName]) tidak menyimpan nilai:

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>().GetName() ??
                memberInfo.Name;
        }

        base.OnParametersSet();
    }
}

Gunakan subkelas dalam QuickGrid komponen. Dalam contoh berikut, DisplayNameColumn yang disebutkan sebelumnya digunakan. Nama "Release Date" disediakan oleh [Display] atribut dalam model, jadi tidak perlu menentukan Title:

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

Atribut [DisplayName] ini juga didukung:

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

Namun, [Display] atribut disarankan karena membuat properti tambahan tersedia. Misalnya, [Display] atribut menawarkan kemampuan untuk menetapkan jenis sumber daya untuk pelokalan.

Data tersimpan di jaringan

Dalam Blazor WebAssembly aplikasi, mengambil data dari API web berbasis JSON di server adalah persyaratan umum. Untuk mengambil hanya data yang diperlukan untuk halaman/viewport data saat ini dan menerapkan aturan pengurutan atau pemfilteran di server, gunakan ItemsProvider parameter .

ItemsProvider juga dapat digunakan di aplikasi sisi Blazor server jika aplikasi diperlukan untuk mengkueri titik akhir eksternal atau dalam kasus lain di mana persyaratan tidak tercakup oleh IQueryable.

Berikan callback yang sesuai dengan tipe delegasi GridItemsProvider<TGridItem>, di mana TGridItem adalah jenis data yang ditampilkan di tabel. Panggilan balik diberi parameter jenis GridItemsProviderRequest<TGridItem>, yang menentukan indeks mulai, jumlah baris maksimum, dan urutan pengurutan data yang akan dikembalikan. Selain mengembalikan item yang cocok, jumlah item total (totalItemCount) juga diperlukan agar halaman dan virtualisasi berfungsi dengan benar.

Contoh berikut memperoleh data dari database publik OpenFDA Food Enforcement.

GridItemsProvider<TGridItem> mengonversi GridItemsProviderRequest<TGridItem> menjadi kueri terhadap database OpenFDA. Parameter kueri diterjemahkan ke dalam format URL tertentu yang didukung oleh JSON API eksternal. Anda hanya dapat melakukan pengurutan dan pemfilteran melalui pengurutan dan pemfilteran yang didukung oleh API eksternal. Titik akhir OpenFDA tidak mendukung pengurutan, sehingga tidak ada kolom yang ditandai sebagai dapat diurutkan. Namun, ini mendukung melompati rekaman (parameter skip) dan membatasi pengembalian rekaman (parameter limit), sehingga komponen dapat mengaktifkan virtualisasi dan menggulir dengan cepat melalui puluhan ribu rekaman.

FoodRecalls.razor:

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

<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 {
    private GridItemsProvider<FoodRecall>? foodRecallProvider;
    private int numResults;

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

            using 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;
    }
}

Untuk informasi selengkapnya tentang memanggil API web, lihat Memanggil web API dari aplikasi ASP.NET CoreBlazor.

QuickGrid perancah

Perancah QuickGrid membangun komponen Razor dengan QuickGrid untuk menampilkan data dalam database.

Perancah menghasilkan halaman Buat, Baca, Perbarui, dan Hapus (CRUD) dasar berdasarkan model data Entity Framework Core. Anda dapat membuat perancah halaman individual atau semua halaman CRUD. Anda memilih kelas model dan DbContext, secara opsional membuat baru DbContext jika diperlukan.

Komponen perancah Razor ditambahkan ke proyek dalam folder yang dihasilkan yang dinamai sesuai dengan kelas model. Komponen yang dihasilkan Index menggunakan QuickGrid komponen untuk menampilkan data. Sesuaikan komponen yang dihasilkan sesuai kebutuhan dan aktifkan interaktivitas untuk memanfaatkan fitur interaktif, seperti penomoran, pengurutan, dan pemfilteran .

Komponen yang dihasilkan oleh perancah memerlukan penyajian sisi server (SSR), sehingga tidak didukung saat berjalan di WebAssembly.

Klik kanan pada Components/Pages folder dan pilih Tambahkan>Item Perancah Baru.

Dengan dialog Tambahkan Item Perancah Baru terbuka ke Terinstal>Umum>Blazor>Razor Komponen, pilih Komponen menggunakan Entity Framework (CRUD). Pilih tombol Tambahkan.

CRUD adalah akronim untuk Buat, Baca, Perbarui, dan Hapus. Perancah menghasilkan komponen buat, edit, hapus, detail, dan indeks untuk aplikasi.

Selesaikan dialog Tambahkan Razor Komponen menggunakan Kerangka Kerja Entitas (CRUD):

  • Daftar dropdown Templat menyertakan templat lain untuk membuat komponen buat, edit, hapus, detail, dan daftar secara khusus. Daftar dropdown ini sangat berguna ketika Anda hanya perlu membuat jenis komponen spesifik yang dipersiapkan untuk kelas model. Biarkan daftar dropdown Template tetap diatur ke CRUD untuk membangun serangkaian komponen lengkap.
  • Di daftar dropdown kelas model, pilih kelas model. Folder dibuat untuk komponen yang dihasilkan dari nama model (jika kelas model diberi nama Movie, folder secara otomatis bernama MoviePages).
  • Untuk kelasDbContext, lakukan salah satu pendekatan berikut:
    • Pilih kelas DbContext yang telah ada yang Anda ketahui memiliki pendaftaran penyedia pabrik (AddDbContextFactory).
    • Pilih tombol + (tanda plus) dan gunakan dialog modal Tambahkan Konteks Data untuk menyediakan nama kelas DbContext baru, yang mendaftarkan kelas dengan penyedia pabrik alih-alih menggunakan jenis konteks secara langsung sebagai pendaftaran layanan.
  • Setelah dialog model ditutup, daftar dropdown Penyedia Database secara default menjadi SQL Server. Anda dapat memilih penyedia yang sesuai untuk database yang Anda gunakan. Opsinya termasuk SQL Server, SQLite, PostgreSQL, dan Azure Cosmos DB.
  • Pilih Tambahkan.

Untuk contoh penggunaan QuickGrid pembuat kerangka, lihat Pembuatan Blazor aplikasi basis data film (Gambaran Umum).

Beberapa kueri EF Core bersamaan memicu System.InvalidOperationException

Beberapa kueri EF Core yang bersamaan dapat memicu System.InvalidOperationExceptionberikut:

System.InvalidOperationException: Operasi kedua dimulai pada instans konteks ini sebelum operasi sebelumnya selesai. Ini biasanya disebabkan oleh utas yang berbeda secara bersamaan menggunakan instans DbContext yang sama. Untuk informasi lebih lanjut tentang cara menghindari masalah thread dengan DbContext, lihat https://go.microsoft.com/fwlink/?linkid=2097913.

Skenario ini dijadwalkan untuk peningkatan dalam rilis ASP.NET Core yang akan datang. Untuk informasi selengkapnya, lihat [Blazor] Meningkatkan pengalaman dengan QuickGrid dan EF Core (dotnet/aspnetcore #58716).

Sementara itu, Anda dapat mengatasi masalah menggunakan ItemsProvider dengan token pembatalan. Token pembatalan menghindari terjadinya kueri bersamaan dengan membatalkan permintaan sebelumnya saat permintaan baru dikirimkan.

Pertimbangkan contoh berikut, yang didasarkan pada komponen Index database film untuk tutorial Membangun aplikasi Blazor database film (Gambaran Umum). Versi yang lebih sederhana yang dibangun ke dalam aplikasi dapat dilihat di aplikasi sampel artikel nomor. Komponen Index yang disusun ke dalam aplikasi digantikan oleh komponen berikut.

Components/Pages/MoviePages/Index.razor:

@page "/movies"
@rendermode InteractiveServer
@using Microsoft.EntityFrameworkCore
@using Microsoft.AspNetCore.Components.QuickGrid
@using BlazorWebAppMovies.Models
@using BlazorWebAppMovies.Data
@inject IDbContextFactory<BlazorWebAppMovies.Data.BlazorWebAppMoviesContext> DbFactory

<PageTitle>Index</PageTitle>

<h1>Index</h1>

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

<p>
    <a href="movies/create">Create New</a>
</p>

<div>
    <QuickGrid Class="table" TGridItem="Movie" ItemsProvider="GetMovies"
            ItemKey="(x => x.Id)" Pagination="pagination">
        <PropertyColumn Property="movie => movie.Title" Sortable="true" />
        <PropertyColumn Property="movie => movie.ReleaseDate" Title="Release Date" />
        <PropertyColumn Property="movie => movie.Genre" />
        <PropertyColumn Property="movie => movie.Price" />
        <PropertyColumn Property="movie => movie.Rating" />

        <TemplateColumn Context="movie">
            <a href="@($"movies/edit?id={movie.Id}")">Edit</a> |
            <a href="@($"movies/details?id={movie.Id}")">Details</a> |
            <a href="@($"movies/delete?id={movie.Id}")">Delete</a>
        </TemplateColumn>
    </QuickGrid>
</div>

<Paginator State="pagination" />

@code {
    private BlazorWebAppMoviesContext context = default!;
    private PaginationState pagination = new PaginationState { ItemsPerPage = 5 };
    private string titleFilter = string.Empty;

    public async ValueTask<GridItemsProviderResult<Movie>> GetMovies(GridItemsProviderRequest<Movie> request)
    {
        using var context = DbFactory.CreateDbContext();
        var totalCount = await context.Movie.CountAsync(request.CancellationToken);
        IQueryable<Movie> query = context.Movie.OrderBy(x => x.Id);
        query = request.ApplySorting(query).Skip(request.StartIndex);

        if (request.Count.HasValue)
        {
            query = query.Take(request.Count.Value);
        }

        var items = await query.ToArrayAsync(request.CancellationToken);

        var result = new GridItemsProviderResult<Movie>
        {
            Items = items,
            TotalItemCount = totalCount
        };

        return result;
    }
}