ここからは一覧表示を扱います。一覧表示については、プロジェクト作成時に付属しているサンプルのWeather.razor(Weather画面)がすでに一覧表示を行っているので、これを見本にして真似しながら画面を作っていきます。
図1 Weather画面。一覧表示のサンプルとして参照する
図2 ソリューションエクスプローラーでWeather.razorの場所を確認
まずは新しいRazorページを追加します。Pagesフォルダーを右クリックして「追加」→「Razorコンポーネント」を選択します。
図3 Pagesを右クリック→「追加」→「Razorコンポーネント」を選択
今回は商品一覧の画面を作りたいので、名前は「ProductPage」にします。
図4 コンポーネント名を「ProductPage」にする
ProductPage.razorが作成されたら、一番上に @page ディレクティブを書き、ダブルクォーテーションで囲んで /product を指定します。URLは /product にしておきます。
図5 @page “/product” でURLを指定
見出しは「商品一覧」にしておきます。
図6 h3見出しに「商品一覧」と記述
この画面の中でProductのリストを作りたいので、まずエンティティ(データベースの1行分のデータをイメージしたもの)としてProductクラスを作ります。Objectsフォルダーを右クリックして「追加」→「クラス」を選択し、ProductEntityという名前で作成します。
図7 ProductEntity.csを作成し、public sealed classと記述(継承させる予定がないのでsealed)
データベースでいうところの列にあたるプロパティを書いていきます。まずProductIdをget onlyのプロパティとして作ります。インスタンス生成後は値を変える予定がないため、getだけにしておきます。同様にProductName、Priceも合わせて3つのプロパティを作ります。
図8 public int ProductId { get; } を記述
続けてコンストラクタを作り、同じように3つの項目(productId, productName, price)を受け取れるようにします。
図9 3つのプロパティとコンストラクタを記述している途中の状態
コンストラクタの中で、受け取った値をそれぞれのプロパティに代入します。これでProductEntityクラスは完成です。
図10 完成したProductEntityクラス(プロパティ3つ+コンストラクタ)
namespace Ander99.Objects
{
public sealed class ProductEntity
{
public ProductEntity(int productId, string productName, int price)
{
ProductId = productId;
ProductName = productName;
Price = price;
}
public int ProductId { get; }
public string ProductName { get; }
public int Price { get; }
}
}
ProductPage.razorに戻り、@codeブロックの中に List<ProductEntity> の変数を用意します。Ctrlキーを押しながらピリオドを押すクイックアクションで、@using Ander99.Objects を追加しておきます。_products = new List<ProductEntity>(); としてインスタンス生成しておきます。
図11 @using Ander99.Objects を追加し、private List<ProductEntity> _products を宣言
図12 _products = new List<ProductEntity>(); でインスタンス生成
画面が起動したときにこのリストへ値を入れたいので、protected override void OnInitialized() を作り、その中で _products.Add(…) を使ってデータを追加します。同期・非同期の書き方がありますが、まずは同期のOnInitializedでやってみます(非同期は別のレクチャーで扱います)。ProductEntity(100, “p100”, 1000) のようなデータを3つ、100・200・300という形で作っておきます。
図13 OnInitialized()メソッドを作成し、_products.Add(new ProductEntity(…)) を記述
図14 商品ID 100・200・300の3件のデータを追加し終えた状態
protected override void OnInitialized()
{
_products.Add(new ProductEntity(100, "p100", 1000));
_products.Add(new ProductEntity(200, "p200", 2000));
_products.Add(new ProductEntity(300, "p300", 3000));
}
続いて、この_productsをHTML側で表示させます。書き方はWeather.razorを見本にします。Weather.razorのelseの中にある <table class=”table”> から </table> までをコピーして、ProductPage.razorのh3の下に貼り付けます。
図15 Weather.razorのtableタグ部分(if文のelse内)を確認
図16 ProductPage.razorのh3見出しの下にtable要素を貼り付け
タイトル行(データグリッドでいう列見出し)は4つありますが、今回は3列にしたいので、1番上のDateだけ残して「商品ID」に書き換え、それをコピー&貼り付けして「商品名」「価格」の合計3列にします。
図17 1つ目の見出しを「商品ID」に書き換え
図18 見出しを「商品ID」「商品名」「価格」の3列にする
次にforeachでぐるぐる回っている部分(<tr><td>…というテーブルの行・データにあたる部分)も、サンプルでは4つありますが、今回は3列に合わせて1つ(1行分)だけ残します。
図19 余分なtd要素(2〜4番目)を選択して削除
foreachで回す対象を forecasts から _products に書き換え、ループ変数の名前は p にします。
図20 foreachの対象forecastsを選択し、_productsに書き換える準備
@p. と入力すると、ProductName・ProductId・Priceの3つがインテリセンスの候補に出てくるので、これを1つずつtd要素の中に入れていきます。
図21 @foreach (var p in _products) に書き換え、@p.でインテリセンスの候補(ProductName等)が表示された状態
図22 @p.ProductId、@p.ProductName、@p.Priceをそれぞれtd要素にバインドし終えた状態
<table class="table">
<thead>
<tr>
<th>商品ID</th>
<th>商品名</th>
<th>価格</th>
</tr>
</thead>
<tbody>
@foreach (var p in _products)
{
<tr>
<td>@p.ProductId</td>
<td>@p.ProductName</td>
<td>@p.Price</td>
</tr>
}
</tbody>
</table>
これで_productsがforeachで回り、3件のデータがあるので3行分のデータが表示されるはずです。あとはこの画面を開けるようにするため、NavMenu.razorを開き、「計測」のひとかたまり(divからdivまで)をコピーして貼り付けます。「計測」の部分は「商品一覧」に、Measureのところのhref属性はproductに書き換えます。アイコンは今回は変更せず同じものにしておきます(変え方は以前のレクチャーを参照)。
図23 NavMenu.razorの「計測」のdivブロックをコピー
図24 複製したブロックのhrefをproductに、表示テキストを「商品一覧」に書き換え
<div class="nav-item px-3">
<NavLink class="nav-link" href="product">
<span class="bi bi-activity-nav-menu" aria-hidden="true"></span> 商品一覧
</NavLink>
</div>
これで実行します。「商品一覧」をクリックすると、3行のデータが表示されました。このように一覧表示ができるので、ぜひやってみてください。
図25 アプリを実行し、/productへ遷移する直前の状態
図26 「商品一覧」画面を実行し、商品ID・商品名・価格の3行が正しく表示された
A01_はじめに
A02_バージョンの確認
A03_プロジェクトの作成
A04_アプリの実行
A05_サンプルプログラムの構成
A06_Razorコンポーネント
A07_Razor構文
A08_@pageでURLを指定する
A09_@rendermode
A10_PageTitle
A11_HTMLの見出し
A12_pタグ
A13_単方向データバインド
A14_単方向データバインドの詳細
A15_Bootstrap
A16_ボタンクリックイベント
A17_イベント引数の受け取り方
A18_ここまでのまとめ
B01_新しいWebページを追加する方法
B02_サイドバーから画面を表示する
B03_サイドバーのアイコンを変更する方法
B04_計測値を表示する
B05_変数に置き換える
B06_最新の値でデータを更新する
B07_@usingで通常のC#コードを呼び出す
B08_画面遷移_aタグ
B09_画面遷移_aタグの見た目をボタンにする
B10_画面遷移_NavigationManagerでの遷移
B11_画面間のパラメータの受け渡し方法
B12_EscapeDataStringでエスケープする
B13_複数のパラメータを渡す
B14_任意のパラメータにする
B15_string以外の型をパラメータで使う方法
B16_DateTime型をパラメータで渡す方法
B17_引数2個のURLも型指定に変更する
B18_パラメータ属性をつけるときの注意点
B19_OnParametersSet
B20_OnInitialized
B21_OnInitializedが2回通る問題の対応
B22_ブラウザが開いている間の値を記憶する方法
B23_値の受け渡しとしてのProtectedSessionStorage
B24_非同期を想定したUIの制御
C01_一覧表示
C02_非同期での一覧表示
C03_table-striped
D01_入力エリア
D02_双方向データバインド
D03_入力データをリアルタイムで通知する方法
D04_placeholder
D05_入力エリアの横幅の調整
D06_テキストチェンジイベントを拾う方法
D07_プルダウン
D08_プルダウンのbootstrap
D09_プルダウンの選択している値をデータバインドで操作する
D10_プルダウンにリストの値を表示する
D11_プルダウンに未選択行を入れる
D12_プルダウンの入力を禁止する
D13_プルダウンのチェンジイベントを取得する
D14_チェックボックス
D15_チェックボックスにラベルを付ける
D16_複数のチェックボックスを並べる
D17_ラジオボタン
D18_ラジオボタンのデータバインド
D19_ラジオボタンのチェンジイベント
D20_ラジオボタンにbootstrapを適応する