Razor記法‐基本

■基本

 ①HTMLとC#の切り替えは[@]で始まり、半角スペースや改行で終わる。

 ex)私は @name です。

 この例では変数nameを@nameと指定し、nameプロパティの値を表示している。

 (*)@nameの前後には半角スペースが必須!

  前に半角スペースがない場合@nameという文字列になり、

  後ろに半角スペースがない場合、[@nameです]という名前の変数を使うことになる

 

 ・@(name)とすれば、スペースが無くとも正しく処理される。

 ・またC#で変数名に使えない文字を使っても、スペースが無くとも問題ない。

  (*)例えばタグなど。<span>@name</span>だと問題ない。

 ②@変数名で処理できるのは、プロパティや変数、メソッド等。

Component間のデータ授受(子⇒親)②

■子で起こした引数有のイベントを親で購読する。

 ●親

 @page "/ParentBmi3"
 <BlazorBmi.Components.BmiChild3 OnResultChanged="@ChanegResult" />
 BMI:@Bmi
 @code{
     public double Bmi { get; set; }
     private void ChanegResult(double result)
     {
         this.Bmi = result;
     }
 }

 

 ●子

 <div>子のイベントを親でハンドル</div>
 <div>身長:<input type="number" @bind="Height" /></div>
 <div>体重:<input type="number" @bind="Weight" /></div>
 <button @onclick="ClickCalc">計算</button>

 @code{
     public double Weight { get; set; } = 60;
     public double Height { get; set; } = 170;
     [Parameter]
     public EventCallback<double> OnResultChanged { get; set; }
     private async void ClickCalc()
     {
         var result = Weight / *1;
         await OnResultChanged .InvokeAsync(result);
     }
}

①親では、子呼び出し時に、子のCallbackイベント名と、そのイベントを

 検知した時に実行したいメソッドを紐づけておく。

 <BlazorBmi.Components.BmiChild3 OnResultChanged="@ChanegResult" />

 OnResultChanged:子のCallbackEvent名

 @ChanegResult:親に定義している、子のonResultChangedイベント検知時に

         行いたい処理(メソッド名)

*1:Height / 100) * (Height / 100

Component間のデータ授受(子⇒親)①

■子での変更を親に伝えたい場合、Event経由で行う必要がある。

 

■親(呼び出し側)
<PJ名.Components.コンポーネントWeight ="@Weight"
  Height ="@Height" @bind-Result="Result" />

//親から子への引き渡しはbindは不要

@code{
    public double Weight { get; set; } = 60;
    public double Height { get; set; } = 170;
    public double Result { get; set; } = 0;
}

 

@bind-Result="Result"で、子で変更したResultの値が親に渡される。

 

■子

<div>
 Height: @Height cm, Weight:@Weight kg.  
</div>
<button class="bnt btn-primary" @onclick="clickCalc">計算</button>
@code{
    [Parameter]
    public double Height { get; set; } = 170.0;
   [Parameter]
    public double Weight { get; set; } = 60.0;
    [Parameter]
    public double Result{get;set; }」

 //パラメータの変更を受け取るイベント
 [Parameter]
    public EventCallback<double> ResultChanged { get; set; }

    //計算
    public async void clickCalc()
    {
        Result = Weight/*1;
        await ResultChanged.InvokeAsync(Result);
    }

 

 

[Parameter]属性付きで、授受したいプロパティを定義

②値変更時に子から親に渡したいプロパティについて、プロパティ名+Changed

 という名前で[Parameter]属性付きでEventCallBackを定義しておく。

③子で変更したプロパティを親に伝える場合、変更したプロパティ

 Changedイベントを、InvokeAsyncで起こす。

 その際、引数に渡す値をセットする。

 上の例でいうと、await ResultChanged.InvokeAsync(Result);

 (*)例えばWeightなどはChangedイベントを呼んでいないので、

  子でWeightの値を変えても親には伝わらない。

 

■親

①親は、コンポーネント呼び出し時、やり取りするパラメータ名を

 @bind-XXX=値という形で子に渡す。

 子で、[Parameter]属性付きで定義されたプロパティ名がXXXにセットされる。

 (この時、インテリセンスが効く)

 

 

 

*1:Height/100)* (Height / 100

Component間のデータ授受(親⇒子)

■ロード時に1回だけ親から子に渡すケース

 ●親

  <PJ名.Components.コンポーネント名 Param名①="test" Param名②="2021" />

  親(コンポーネントを使う側)では、"パラメータ名:値"という形で

  コンポーネントに値を渡す。パラメータ名は、子で定義した[Parameter]属性

  付きのプロパティ名

 

 ●子

  <div">Copyright 2020 by @Name @Year</div>
  @code {
      [Parameter]
      public string Name  { get; set; }
      [Parameter]
      public int Year { get; set; }
  }

  パラメータは、[Parameter]属性を付けたプロパティで定義する。

  

bindする場合としない場合

■bindする場合としない場合

 ①<input type="text" @bind=変数 />

 ②<input type="text" @value=変数 />

①も②もどちらも変数の値がセットされるが、

・bindした場合は、テキストの値を画面で変更時、変更値がCode側の変数に格納され、

 変数の値をCode側で変更時、画面に反映される。(双方向)

・bindしない場合は、Code側での値変更が画面に反映はされるが、

 画面で変更した値は変数には格納されない。(単方向)

双方向データバインディング

■値を別の要素に表示する

@*テキストボックスで入力*@

<input class="form-control" @bind="Title"/>

@*入力値が保存されるプロパティ*@

private string Title { get; set; }

@*入力値をラベルに表示*@

<label class="col-form-label">@Title</label>

 

■即時反映する

上記例の場合、ロストフォーカス時にラベルに反映される。

入力値を即時反映する場合は、"oninput"inputにイベントを追加する。

<input class="form-control"  @bind:event ="oninput" @bind="Title2"  />

(*)この時、bindをbind-valueにすると、inputのvalue要素へのbindとなる

 value要素へのbindの場合、単方向のバインドとなり、画面での入力が

 プロパティに反映されない為、oninputイベントは走らない。

 

■入力値を加工して反映する

入力値はプロパティのSetterを通して保存され、Getterを通して反映される為、

そこに処理を追加してやれば良い。

(*)入力値に"test"を足して反映

 private string _Title2;
    public string Title2
    {
        get { return _Title2; }
        set { _Title2 = value + "test"; }
    }

 

■Styleにバインドする

<input type ="number" @bind ="fontSizeNum" class="form-control" />
<div style="font-size:@(fontSizeNum)pt">確認するよ</div>
@code
{
    private int fontSizeNum{ get; set; } = 12;
}

 

CSSにバインドする

<input type ="number" @bind ="fontSizeNum" class="form-control" />
<div class="fontSize">確認するよ</div>
<style>
    div.fontSize{color:green;font-size:@(fontSizeNum)pt;}
</style>
@code
{
    private int fontSizeNum{ get; set; } = 12;
}

実際はClass属性をバインド先にし、Classを切り替える使い方が良いが。

 

Child Components

■Components

 ・Blazorで作る一つ一つの要素(Pageなど)をComponentsという。

  機能ごとに個別にComponentsを作り、それを適宜ページで呼び出す

  ことでシステムを構築していくことができる

 

■Child Cpomponents

 ・Pageの任意の場所から呼び出すComponentをChild Componentという。

 ①配置場所

  ・通常、Componentsフォルダを作りその中に配置する。

 ②作成方法

  ・Pageと同じだが、ルーティングに関する記載は不要

  ex)ChildRazor.razor

   <div>@Item.Name</div>
   <div>@Item.Height</div>
   @code {

    @*パラメータ付きで呼ばれる場合はParameter属性付与*@
       [Parameter]
       public BmiItem Item { get; set; }
       [Parameter]
       public RenderFragment ChildContnet { get; set; }
   }

   @*以下のClassは別ファイルで定義*@

   @code {
       public class BmiItem
       {
           public string Name { get; set; }
           public double Height { get; set; }
    }
   }

 

 ③呼び方

  呼び出したいrazor内で、以下のように呼ぶ。

  <BlazorBmi.Components.ChildRazor Item="@it" />