背景
Ignite UI for Blazor が提供するグリッドコンポーネント、IgbGrid コンポーネントを使ったプログラムにおいて、セル内の描画内容をカスタマイズするために、BodyTemplate や InlineEditorTemplate パラメーターにカスタムの描画処理 (セルテンプレート) を実装することがあります。
<IgbGrid Data="_data" ...> ... <IgbColumn Filed="@nameof(Person.Name)"> <BodyTemplate> <!-- ここに任意の HTML レンダリング処理を書ける --> </BodyTemplate> </IgbColumn> ... </IgbGrid> @code { private List<Person> _data = ...
このとき、そのセル内に描画されるべき値 (つまり、列を定義する IgcColumn コンポーネントにおける Field パラメーターに指定された名前のプロパティの値) は、テンプレート内で暗黙的に参照できる引数、“context” を介して、context.Cell.Value として参照可能です。
<IgbGrid ...> ... <IgbColumn Filed="@nameof(Person.Name)"> <BodyTemplate> <!-- テンプレート内では暗黙の引数 "context" が参照できる --> <span @key="context.Cell.Id.RowID"> <!-- context.Cell.Value にはこのセルに表示されるべき値が格納されている (この例だと、IgcColumn の Field に "Name" と指定しているので、Name プロパティの値) --> @context.Cell.Value <span> </BodyTemplate> </IgbColumn> ... </IgbGrid>
しかし要件によっては、そのセルテンプレートに表示すべき値のみならず、その値の由来である元の行データであったり、あるいは、その行データから同行の別の列 (プロパティ) を参照したい場合があります。
このような場合は、以下の手順で参照可能です。
手順
まず IgbGrid コンポーネントの PrimaryKey パラメーターに、そのグリッドコンポーネントにバインドするデータ型のうち、一意に行を特定できるユニーク値を持つプロパティの名前を指定してください。
<IgbGrid PrimaryKey="@nameof(Perosn.Id)" ...
次に、セルテンプレート内ですが、テンプレート内の暗黙引数 context を介して、context.Cell.Id.RowID プロパティを参照すると、そのセルの描画元となっている行データの、IgbGrid の PrimaryKey パラメーターで指定した名前のプロパティ値が取得できます。
<IgbGrid PrimaryKey="@nameof(Perosn.Id)" ...> <IgbColumn ...> <BodyTemplate> <!-- この例では、ここで context.Cell.Id.RowID を参照すると、 このセルにバインドされる行データの、Id プロパティの値が取得できる --> </BodyTemplate> ...
続けて context.Parent には、そのセルを抱えているグリッドコンポーネント (IgbGrid) への参照が格納されています。これを介して、IgbGrid の Data パラメーターを参照することで、バインドされている元データ全体にもアクセスできます。
<IgbGrid Data="_data" ...> ... <IgbColumn Filed="@nameof(Person.Name)"> <BodyTemplate> @{ // context.Parent に、このセルを持つ IgbGrid への参照がある var grid = context.Parent as IgbGrid; // IgbGrid の Data を見れば、バインドされているデータ全体を参照できる var rows = grid?.Data as List<Person>; } </BodyTemplate> </IgbColumn> ... </IgbGrid> @code { private List<Person> _data = ...
この二者を組み合わせて、バインドされている元データ全体から、PrimaryKey に指定された名前のプロパティ値が、context.Cell.Id.RowID に一致する行を探索することで、セルテンプレート内から行データを取得することができます。
<IgbGrid Data="_data" PrimaryKey="@nameof(Person.Id)" ...> ... <IgbColumn Filed="@nameof(Person.Name)"> <BodyTemplate> @{ // context.Parent に、このセルを持つ IgbGrid への参照がある var grid = context.Parent as IgbGrid; // IgbGrid の Data を見れば、バインドされているデータ全体を参照できる var rows = grid?.Data as List<Person>; // context.Cell.Id.RowID に PrimaryKey に指定された名前の // プロパティ値がある var rowId = context.Cell.Id.RowID; // 以上を元にバインド元データを探索すればこのセルの元データ行を取得できる var row = rows?.First(r => r.Id == rowId); } </BodyTemplate> </IgbColumn> ... </IgbGrid> @code { private List<Person> _data = ...
ひとたび行データが取得できれば、同じ行データ内の任意のプロパティを参照可能です。
<IgbGrid ...> ... <IgbColumn Filed="@nameof(Person.Name)"> <BodyTemplate> @{ var grid = context.Parent as IgbGrid; var rows = grid?.Data as List<Person>; var rowId = context.Cell.Id.RowID; var row = rows?.First(r => r.Id == rowId); // 行データがわかれば、他のプロパティ (列) の値も参照可能 var iconUrl = row?.Country switch { Country.India => "./img/in.png", Country.Japan => "./img/jp.png", Country.UnitedStates => "./img/us.png", _ => "./img/no-image.png" }; } <span @key="context.Cell.Id.RowId"> <img src="@iconUrl" /> <span>@context.Cell.Value</span> </span> </BodyTemplate> </IgbColumn> ... </IgbGrid> @code { private List<Person> _data = ...
実際の実装においては、上記のようにテンプレート内でインラインで実装するのではなく、コンポーネント内のメソッドに切り出したほうがよいかと思います。
<IgbGrid ...> ... <IgbColumn Filed="@nameof(Person.Name)"> <BodyTemplate> <span @key="context.Cell.Id.RowID"> <img src="@GetIconUrl(context)" /> <span>@context.Cell.Value</span> </span> </BodyTemplate> </IgbColumn> ... </IgbGrid> @code { private List<Person> _data = ... private string GetIconUrl(IgbCellTemplateContext context) { var grid = context.Parent as IgbGrid; var rows = grid?.Data as List<Person>; var rowId = context.Cell.Id.RowID; var row = rows?.First(r => r.Id == rowId); // 行データがわかれば、他のプロパティ (列) の値も参照可能 var iconUrl = row?.Country switch { Country.India => "./img/in.png", Country.Japan => "./img/jp.png", Country.UnitedStates => "./img/us.png", _ => "./img/no-image.png" }; return iconUrl; } ...
実際に動作する完全な形のサンプルプログラムは、以下のリンク先から参照いただけます。