🐥

Udemy Blazor受講内容まとめ

2025/02/18に公開

講義名:Blazor - The Complete Guide [.NET 9] [2024] [E-commerce]

Create Blazor Project

  • Blazor Web AppProjectを生成 → .NET 9.0設定

Blazor Fundamentals

  • 経路を指定するためには @page が必要
  • @code を使ってC#コードと一般的に必要なコードを使うことができる。
  • 単方向バインディング vs 双方向データバインディング
    • 単方向バインディング:設定した値だけが画面に出力される。画面に値を入力しても値が変わらない。
    • 双方向データバインディング:設定した値だけが画面に出力されるだけじゃなく画面に値を入力すると値が変わる。
  • 双方向データバインディング時、画面に値を入力後テキストボックスの外部をクリックすると値が変わる。
    • @bind:event="on iniput"を追加すると入力と同時に値が変わる。
  • FirstOrDefault:最初の要素を持ってくる。最初の要素がないとデフォルト値(参照型の場合はnull)をリターンする。
  • @using Models を使うと新しいモデルを生成する時 Models が省略できる。
new Models.Porduct_Prop { ...} → new Product.Prop {...}
  • class="col 11 p-4":12列 4パディング → CSS要素
  • @page 追加時、基本的に探索経路を作成するとき / が必要
@page "/learnBalzor/demoProduct"
  • 一部が使われる要素の場合はファイル名にアンダーバーを追加する。
    • 全体ページに一部が使われる削除ボタン Component を生成:_DeleteButton.razor
  • 親要素から変数を使いたい場合はパラメーター属性が必要
    * 親要素 _DeleteButtonComponent のパラメーター
    [Parameter] public int Id {get; set;} を子要素で使うことが可能
  • EventCallback:チェックボックスをクリックするとカウントが増えてチェックを外すとカウントが減る。
DemoProduct.razor
<p>Favorite Count:@FavoriteCount</p>
<div class="p-2 mt-2">
    <div class="row">
        @foreach(var prod in ProductList)
        {
            <IndividualProduct Product="prod" OnFavoriteUpdated="FavoriteCountChange"></IndividualProduct>
        }
    </div>
</div>

@code
{
public int FavoriteCount { get; set; } = 0;
protected void FavoriteCountChange(bool isSelected)
{
    if(isSelected)
    {
        FavoriteCount++;
    }else
    {
        FavoriteCount--;
    }
}
IndividualProduct.razor
<input type="checkbox" @onchange="FavoriteUpdated" />Add to Favorites

@code
{
    [Parameter]
    public EventCallback<bool> OnFavoriteUpdated { get; set; }
    private async Task FavoriteUpdated(ChangeEventArgs args)
    {
        await OnFavoriteUpdated.InvokeAsync((bool)args.Value);
    }
}

コードの流れ

  1. FavoriteCount:0が出力される。
  2. Add to Favoritesチェックボックスを選択/解除するとFavoriteUpdatedメソッドが呼ばれる
    →@onchange="FavoriteUpdated"
  3. FavoriteUpdatedメソッドが動作する流れは以下
    3-1. ChangeEventArgs args → @onchangeイベントが発生する時、変更された値(チェックボックスの状態)が args.Value に保存される。
    3-2. args.Valueはobject型なので (bool)args.Value に変換して true/false値をゲットする。
    3-3. OnFavoriteUpdated.InvokeAsync((bool)args.Value) → 親コンポーネント(DemoProduct.razor)の FavoriteCountChange(bool isSelected)メソッドを読んでFavoriteCountを増加/減少させる。

Q1. OnFavoriteUpdatedメソッドがどうFavoriteCountChangeメソッドを呼ぶ?
DemoProduct.razorで OnFavoriteUpdated="FavoriteCountChange" を設定する。つまり、OnFavoriteUpdatedはFavoriteCountChangeメソッドを意味する。
ユーザーがチェックボックスをクリックするとFavoriteUpdated()が実行される。
実行される理由はチェックボックスの選択/解除は変化が起きたOnChangeだから。
チェックボックスの状態(true/false)をargs.Valueに保存してOnFavoriteUpdate.InvokeAsync((bool)args.Value) を呼ぶ。
OnFavoriteUpdatedはFavoriteCountChangeを意味するので ```FavoriteCountChange(bool isSelected)''' 実行される。
OnFavoriteUpdatedは FavoriteCountChangeのリンク!

Q2. なぜ @onchange="FavoriteUpdated" が必要?
@onchange="FavoriteUpdate" がないとチェックボックスの状態が変更されても FavoriteUpdatedメソッドが呼ばれないので FavoriteCount値がアップデートされない。
つまり、イベントバインディング(onchange)が必要

  • EventCallback:特定エリアをクリックすると選択した商品名が画面に出力される。
DemoProduct.razor
<p>Selected Product:@SelectedProduct</p>
<div class="p-2 mt-2">
    <div class="row">
        @foreach(var prod in ProductList)
            {
                <_IndividualProduct Product="prod" OnSelectedProductChange="Updated Selected Product"> </_IndividualProduct>
            }
    </div>
</div>

@code
{
    public string SelectedProduct { get; set;} = string.Emprty;
    protected void UpdatedSelectedProduct(string productName)
    {
        SelectedProduct = productName;
    }
}
_IndividualProduct.razor
<div class="bg-light border col-6" @onclick="(args)=>SelectedProductUpdated(args.Product.Name)">
<h4 class="text-secondary">Product- @Product.Id </h4>
Name - @Product.Name <br />
</div>

@code
{
    [Parameter]
    public Product product { get; set;}
    [Parameter]
    EventCallback<string> OnSelectedProductChange { get; set; }
    private async Task SelectedProductUpdated(MouseEventArgs args, string productName)
    {
        await OnSelectedProductChange.InvokeAsync(productName);
    }
}

コードの流れ

  1. ループ文で作成した <_IndividualProduct> をクリックすると UpdateSelectedProductメソッドが実行され OnSelectedProductChange が呼ばれる。
  2. SelectedProductUpdated(args.Product.Name)が実行される。
    2-1. このメソッドは選択した商品名を親コンポーネント(DemoProduct.razor)に渡す機能
    2-2. A商品をクリックした場合、@onclick="(args)=>SelectedProductUpdated(args,Product.Name)" が実行される。
SelectedProductUpdated(args, "A"); になる。

2-3. await OnSelectedProductChange.InvokeAsync(Product.Name) が実行されて親コンポーネントに値を渡す。
2-4. 親コンポーネントで OnSelectedProductChagneUpdatedSelectedProductメソッドとつながっているので、OnSelectedProductChange.InvokeAsync(args,"A") が呼ばれると UpdateSelectedProduct("A") が実行される。
2-5. SelectedProduct=productName で SelectedProduct値が A に変わる。

Q1. @onclick="(args)=>SelectedProductUpdated(args,Product.Name)"の補足
このコードはパラメーターを渡す。
この例ではパラメーターが商品名になる。
Blazorではイベントハンドラー(@onclick)を使う時基本的にイベント情報(MouseEventArgs)が自動的に渡されるけど追加のパラメーターと一緒に渡すためにはラムダ式が必要

(args)=>SelectedProductUpdated(args,Product.Name)
//args:クリック時自動的に渡すMouseEventArgs
//Product.Name:追加で渡したいデータ
⇒argsだけじゃなくProduct.Nameも渡すために(args)中にパラメーター2つを入れることを表現するためにラムダ式を使った

Discussion