Blazor01

BlazorでのWebアプリケーション開発手法1【C#】B18_パラメータ属性をつけるときの注意点

ここまで、URLを介して計測画面(MeasurePage.razor)にパラメータを渡す方法を見てきました。今回はその総まとめとして、[Parameter]属性を使ううえで守らなければならないルールを、実際にコードを崩しながら確認していきます。

図1 現在のMeasurePage.razor。MeasureValue・MeasureDate・MeasureAreaの3つが[Parameter]属性付きのプロパティとして宣言されている

① アクセス修飾子は必ずpublicにする

パラメータにしたいプロパティは、アクセス修飾子を必ずpublicにする必要があります。試しにMeasureValueプロパティの修飾子をprivateに変更してみます。

図2 修飾子をprivateに変更しようとしているところ

この状態でビルドするとコンパイルエラーになります。internalに変更した場合も同様で、エディタ上には次のような警告が表示されます。

図3 internalに変更した際に表示されるBL0004エラー。「Component parameter … should be public.」(コンポーネントパラメーターはpublicである必要があります)と警告されている

つまり、[Parameter]属性を付けるプロパティは、public以外の修飾子(private・internalなど)にすることはできません。

② getとsetの両方が必要

次に、アクセサーの構成についてです。MeasureValueプロパティをget;だけにしてみます。

図4 getのみにした場合。BL0001エラー「should have a public setter.」(publicなsetterが必要)が表示される

get;のみではエラーになり、public setterを付けるよう求められます。では、setのアクセス修飾子をprivateにしたらどうでしょうか。

図5 private set;にした場合も同じくBL0001エラーが表示され、publicなsetterが必要と警告される

private setでも同じくエラーになります。つまり、[Parameter]属性を付けるプロパティは、getとsetの両方をpublicで公開しておく必要があります。

③ プロパティでなければならない

[Parameter]属性は、そもそもプロパティにしか付けられません。フィールド(変数)にしてみます。

図6 get; set; を削除して単なるフィールド(public float MeasureValue;)に書き換えたところ

続けて、丸カッコを付けてメソッドの形にしてみます。

図7 メソッドの形(public float MeasureValue())に書き換えたところ

いずれの場合もエラーになります。[Parameter]属性はget/setを持つプロパティに対してのみ付与できるということです。

④ プロパティ名をURLと一致させる

ここまでの3点を守ってプロパティを元に戻したうえで、今度はプロパティ名そのものを変更してみます。MeasureValueをMeasureValueAに変更すると、コンパイル自体は通ります。

図8 @pageディレクティブのURLパラメータ名をMeasureValueAに変更したところ。この時点ではコンパイルエラーにはならない

しかし、実際にアプリを実行してこのページを開こうとすると、実行時エラーになります。

図9 実行時に表示されるエラー画面。「Object of type ‘Ander99.Components.Pages.MeasurePage’ does not have a property matching the name ‘MeasureValueA’.」(MeasurePageにMeasureValueAという名前に一致するプロパティがない)と表示されている

@pageディレクティブに書いたURLパラメータ名({MeasureValueA}など)と、プロパティ名は完全に一致していなければなりません。名前をMeasureValueに戻せば、正しく動作します。

⑤ プロパティの初期値は意味を持たない

最後にもう一つ、見落としがちな注意点です。現在、サイドバーの「計測」メニューから計測画面を開くとURLにパラメータが付かないため、計測値は0、計測日時は0001/01/01 0:00:00、計測場所は空文字(それぞれfloat・DateTime・stringの既定値)が表示されます。

図10 サイドバーの「計測」から遷移した状態。URLにパラメータがないため、計測値:0、計測日時:0001/01/01 0:00:00、計測場所は空欄になっている

「では、プロパティ自体に初期値を設定しておけば、その値が表示されるのでは」と考え、MeasureValueに999f、MeasureDateにDateTime.MaxValue、MeasureAreaに”しょきち”という初期値を設定してみます。

[Parameter]
public float MeasureValue { get; set; } = 999f;
[Parameter]
public DateTime MeasureDate { get; set; } = DateTime.MaxValue;
[Parameter]
public string MeasureArea { get; set; } = "しょきち";

 

図11 MeasureValue・MeasureDate・MeasureAreaの3プロパティに、それぞれ999f・DateTime.MaxValue・”しょきち”という初期値を設定したところ

この状態で実行し、再びサイドバーの「計測」から画面を開いてみますが、結果は変わらず計測値:0、計測日時:0001/01/01 0:00:00のままです。

図12 初期値を設定したあとも、パラメータなしで開くと表示は変わらず0・0001/01/01 0:00:00のままとなる

つまり、プロパティ自体に書いた初期値には意味がありません。理由は、Razorコンポーネントが生成される瞬間には確かに999などの初期値でプロパティが初期化されますが、そのすぐ後に呼び出し元(URL)からパラメータが渡されるためです。URLにパラメータが指定されていない場合は、型の既定値(floatなら0、DateTimeならMinValue、stringならnullで結果的に空文字)で上書きされてしまいます。

パラメータが指定されていないときに独自の初期値を使いたい場合は、プロパティの初期値ではなく、別の仕組み(ライフサイクルメソッドなどでのタイミング調整)で対応する必要があります。これについては、次回以降のレクチャーで扱っていきます。

まとめ

[Parameter]属性を付けるプロパティには、次の5つのルールがあります。

・アクセス修飾子は必ずpublicにする(private・internalは不可)

・getとsetの両方をpublicで公開する(get onlyやprivate setは不可)

・フィールドやメソッドではなく、プロパティである必要がある

・プロパティ名は@pageディレクティブのURLパラメータ名と完全に一致させる

・プロパティに書いた初期値は、URLパラメータが渡された時点で型の既定値に上書きされるため意味を持たない

BlazorでのWebアプリケーション開発手法1【C#】

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を適応する