Lightning Blog
Blazor記事イメージ画像

【Blazor】 Virtualizeコンポーネントの使い方

更新日:2023/07/26
Virtualizeコンポーネントは、Blazorのデータ表示において非常に便利なコンポーネントです。 このコンポーネントを使用することで、 現在画面に表示されている部分のデータだけがレンダリングされ、 それ以外のデータは非表示となります。 これにより、大規模なデータの表示においても、パフォーマンスの高いUIを作成することができます。 それでは使い方をみていきましょう。

    目次

  • 仮想化コンポーネントを使う前の準備
  • Virtualizeコンポーネント
  • 非同期処理に対応しよう
  • まとめ

仮想化コンポーネントを使う前の準備

セクション画像

表示するデータを用意します。 今回はProductクラスを定義し、そのクラスのコレクションを用いながら、検証していきます。


public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Virtualizeコンポーネント

セクション画像

Virtualizeコンポーネントを使っていきます。 まずは使用例をみていきましょう。


@page "/"
@using Blazor_VirtualizeComponent.Data;

<div class="container">

    <div class="row">

        <div class="col-6">

            @* 仮想化コンポーネント *@
            <Virtualize Context="product" Items="@products">
                <div>@product.Name - $@product.Price</div>
            </Virtualize>

        </div>

        <div class="col-6">

            @* 仮想化なし *@
            @foreach (var product in products)
            {
                <div>@product.Name - $@product.Price</div>
            }

        </div>

    </div>

</div>

@code {

    private List<Product> products;

    protected override void OnInitialized()
    {
        base.OnInitialized();

        products = new();
        for (int i = 0; i < 1000; i++)
        {
            products.Add(new() { Name = $"ProductName{i}", Price = 10 * i });
        }
    }

}

Virtualizeコンポーネントのパラメータを指定します。 Contextには、Virtualizeコンポーネント内でコレクションの要素にアクセスするための変数名を設定します。 Itemsには表示したいデータのコレクションproductsを指定します。 今回は仮想化コンポーネントの特徴を分かりやすくするため、左列に仮想化コンポーネント、右列に仮想化なしの状態を表示しています。

それでは実行してみましょう。 スクロールして比較してみると、左側の仮想化コンポーネントでは常時更新されている様子が確認できると思います。

レンダリング範囲

非同期処理に対応しよう

セクション画像

データベースから大量データを取得する場合など、 表示に時間がかかる処理を行うパターンがほとんどだと思います。 ただし、取得処理中にコンポーネントに何も表示されていないと、ユーザーが違和感を感じてしまいます。 そのため、読み込み中の場合には、[読み込み中・・・]という表示が出るように、 コードを変更していきます。


@page "/"
@using Blazor_VirtualizeComponent.Data

<Virtualize Context="product" ItemsProvider="LoadProducts">
    <ItemContent>
        <div>@product.Name - $@product.Price</div>
    </ItemContent>
    <Placeholder>
        <div>読み込み中...</div>
    </Placeholder>
</Virtualize>

@code {

    /// <summary>
    /// 製品情報読み込み
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    private async ValueTask<ItemsProviderResult<Product>> LoadProducts(ItemsProviderRequest request)
    {
        var startIndex = request.StartIndex;
        var count = request.Count;
        var items = new List<Product>();

        // 要求されたデータ範囲に基づいて製品リストを生成
        for (int i = startIndex; i < startIndex + count && i < 1000; i++)
        {
            items.Add(new Product { Name = $"ProductName{i}", Price = 10 * i });
        }

        await Task.Delay(500);

        // 第二引数に、実際の全製品数を指定することで、スクロールの終端を正しく制御する(1000は仮)
        return new ItemsProviderResult<Product>(items, 1000);
    }

}

変更前のVirtualizeコンポーネントでは、Itemsというパラメータを使用していましたが、 今回は初期化の段階において、値を全て取得するわけではありません。 画面の表示範囲が変更されたら、その範囲のみデータを取得するようにしていきます。 そのような仕様にするには、ItemsProviderというパラメータを使用します。 このパラメータには、表示範囲に応じた値取得ロジックを設定します。 値取得ロジックは、引数であるItemsProviderRequestに表示範囲の開始インデックスや表示される項目数などの情報が組み込まれていますので、 それをもとに実装していきます。 値取得ロジックを作成したら、Virtualizeコンポーネントの子コンポーネントを指定します。 ItemContentには実際のデータの表示内容を定義し、 Placeholderには読み込み中に表示する内容を定義します。

それでは実行してみましょう。 画面の表示範囲が変わると、データ取得中の場合は[読み込み中...]と表示されることが確認できます。

非同期対応後

まとめ

セクション画像

今回は仮想化コンポーネントについて解説しました。 DBから大量のデータを取得する場合に便利だと思いますので、是非使ってみてください。


ブログ内の記事で書かれているサンプルコードは、GitHubから確認する事ができます。 是非参考にしてみてください。

この本では、Blazorの基本から高度なテクニックまで、実際のプロジェクトに役立つ知識を網羅しています。 初心者から経験者まで、Blazorを扱うすべての開発者にとっての必読書です。 この記事の執筆者も参考にした「Blazor入門」で、あなたのBlazorスキルを飛躍的に向上させませんか?

合わせて読みたい

カード画像
コンポーネントにのみCSSを適用する方法

Blazorで特定のコンポーネントに限定したCSSを適用する方法を紹介。.NET5から導入されたCSS分離を活用し、他のコンポーネントやライブラリとのCSS競合を回避。コンポーネント[CssIsolationComponent.razor]とそのCSS[CssIsolationComponent.razor.css]を作成。この技術により、[CssIsolationComponent.razor]のpタグ部分の背景だけが赤くなることを示す。効率的なデザイン管理のためにCSS分離の使用を推奨。

更新日:2023/07/26

カード画像
InputFileを使ったBlazorファイルアップロード&ダウンロード

この記事では、Blazorと.NET5のInputFileコンポーネントを使ったファイルアップロードとダウンロードの方法を解説します。具体例とサンプルコードを交えて、実装手順を詳細に説明します。

更新日:2024/06/20

An error has occurred. This application may no longer respond until reloaded. Reload 🗙