読み込み専用プロパティを @bindに割り当てるとエラーになる

読み込み専用プロパティを @bindに割り当てるとエラーになる現象を紹介します。

エラー発生例

コード

Blazorアプリケーションで下記のコードを準備します。
Pages/BindError.razor
@page "/BindError"
@inherits BindErrorModel
<h3>TextBox Bind Demo</h3>

<input id="text1" type="text" @bind="@value1"/><br/>
<button @onclick="ButtonClick">Button1</button>
<div>@InputText</div>
Pages/BindError.razor.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Components;

namespace BindDemo.Pages
{
  public class BindErrorModel : ComponentBase
  {
    public string value1 { get; }
    public string InputText { get; set; }

    public void ButtonClick()
    {
      InputText = value1 + " が入力されました";
    }

  }
}
app.razor
<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData"/>
    </Found>
    <NotFound>
        <LayoutView>
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>
_Imports.razor
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop

現象の確認

ビルドすると、次のエラーメッセージが表示され、ビルドに失敗します。
エラーメッセージ
エラー:CS0200
プロパティまたはインデクサー 'BindErrorModel.value1' は読み取り専用であるため、割り当てることはできません


解説

razorページで、inputタグの@bind属性に value1 を指定しています。
<input id="text1" type="text" @bind="@value1"/><br/>

ページモデルクラスで、value1 を読み込み専用プロパティとして定義しています。~
  public class BindErrorModel : ComponentBase
  {
    public string value1 { get; }

    /* 中略 */
  }

原因

bind属性に書き込みのできない変数/プロパティを指定しているため、ビルドエラーが発生します。

対処法1 : メンバ変数または、読み書き可能なプロパティに変更する

ページモデルクラスのコードを以下に変更します。
Pages/BindError.razor.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Components;

namespace BindDemo.Pages
{
  public class BindErrorModel : ComponentBase
  {
    public string value1 { get; set;}
    public string InputText { get; set; }

    public void ButtonClick()
    {
      InputText = value1 + " が入力されました";
    }

  }
}

または以下のコードでも同じ動作となります。
Pages/BindError.razor.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Components;

namespace BindDemo.Pages
{
  public class BindErrorModel : ComponentBase
  {
    public string value1;
    public string InputText { get; set; }

    public void ButtonClick()
    {
      InputText = value1 + " が入力されました";
    }

  }
}

変更後にプロジェクトを実行し、(アプリケーションルートURL)/BindError にアクセスします。下図のページが表示されます。

テキストボックスに文字列を入力し、[Button1]ボタンをクリックします。

入力した文字列がページ内に表示されます。

対処法2 : value属性に変更する

テキストボックスの入力値を受け取る必要がなく、テキストボックスに値を設定するだけの場合には、 別の対処方法として、value属性に変更する方法もあります。
以下のコードに変更します。
Pages/BindError.razor
@page "/BindError"
@inherits BindErrorModel
<h3>TextBox Bind Demo</h3>
<input id="text1" type="text" value="@value1"/><br/>
<button @onclick="ButtonClick">Button1</button>
<div>@InputText</div>
Pages/BindError.razor.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Components;

namespace BindDemo.Pages
{
  public class BindErrorModel : ComponentBase
  {
    public string value1 { get; }
    public string InputText { get; set; }

    public BindErrorModel()
    {
      value1 = "初期値です。";
    }

    public void ButtonClick()
    {
      InputText = value1 + " が入力されました";
    }

  }
}

inputタグのvalue属性であれば、読み込み専用プロパティを指定できビルドエラーにもなりません。 ただし、入力内容を指定した変数に反映することはできません。

変更後にプロジェクトを実行し、(アプリケーションルートURL)/BindError にアクセスします。下図のページが表示されます。 ページモデルで設定したvalue1の初期値がテキストボックスに反映されていることが確認できます。

テキストボックスに文字列を入力し、[Button1]ボタンをクリックします。

value属性に指定したため、テキストボックスに入力した文字列をページモデル側で受け取ることはできません。 value1プロパティに設定した初期値の文字列がページにも表示される動作となります。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-07-01
作成日: 2022-07-01
iPentec all rights reserverd.