ASP.NET Core Razor Pages アプリケーションで動的に複数のチェックボックスをページに配置する - ASP.NET Core

ASP.NET Core アプリケーションで動的に複数のチェックボックスをページに配置するコードを紹介します。

概要

こちらの記事では ASP.NET Webフォームで動的に複数のチェックボックスを配置してチェック状態を検出するコードを紹介しました。 この記事では、Razor Pagesで複数のチェックボックスを動的に配置してチェック状態を取得するコードを紹介します。

プログラム例1: シンプルな例

ASP.NET Core Webアプリケーションのプロジェクトを作成します。
作成後、プロジェクトの直下にPagesフォルダを作成します。

コード

以下のコードを記述します。
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();

app.UseRouting();
app.MapRazorPages();
app.Run();

Pagesフォルダ内にRazor Pageを作成します。
cshtmlファイルのコードは次の通りです。
/Pages/Checkbox1.cshtml
@page
@model DynamicCheckboxCore.Pages.Checkbox1Model
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
  <head>

  </head>
  <body>
    <h2>動的なチェックボックスのデモ</h2>

  <form method="post">
    @{
      for (int i=0; i<Model.myList.Count; i++){
        <div><input id="checkbox_@Model.myList[i].Id" type="checkbox" asp-for="CheckBoxChecked![i]" /><label for="checkbox_@Model.myList[i].Id">@Model.myList[i].Name</label></div>
      }
    }
    <input type="submit" ID="Button1" value="Exec" class="FormButton" asp-page-handler="Action" />
  </form>

  @Html.Raw(Model.OutMessage)

  </body>
</html>
/Pages/Checkbox1.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DynamicCheckboxCore.Pages
{
  public class Checkbox1Model : PageModel
  {
    public class MyItem
    {
      public int Id { get; set; }
      public string Name { get; set; } = "";
    }

    public List<MyItem> myList = new List<MyItem>();

    [BindProperty]
    public bool[]? CheckBoxChecked { get; set; }

    [BindProperty]
    public string OutMessage { get; set; } = "";

    public void OnGet()
    {
      CreateList();
    }

    public void OnPostAction()
    {
        for (int i=0; i < CheckBoxChecked!.Length; i++)
        {
          if (CheckBoxChecked[i] == true)
          {
            OutMessage += string.Format("<p>{0:d}のチェックボックスがチェックされています。</p>",i);
          }
        }
      
    }

    private void CreateList()
    {
      myList.Add(new MyItem { Id = 200, Name = "ぺんぎんクッキー" });
      myList.Add(new MyItem { Id = 201, Name = "しろくまアイス" });
      myList.Add(new MyItem { Id = 202, Name = "かるがもサブレ" });
      myList.Add(new MyItem { Id = 203, Name = "らくだキャラメル" });
      myList.Add(new MyItem { Id = 204, Name = "くじらケーキ" });
      myList.Add(new MyItem { Id = 205, Name = "かぴばらタルト" });
    }
  }
}

解説

Program.cs

Program.csファイルはRazorPagesアプリケーションの標準的なコードです。詳しくはこちらの記事を参照してください。

/Pages/Checkbox1.cshtml

RazorPageのcshtmlファイルでは、forループを利用し、myListのリスト項目をひとつずつアクセスして、CheckBoxをページに配置しています。
asp-for属性で指定しているCheckBoxCheckedプロパティにチェックボックスのチェック状態は保存されます。また、チェックボックスの数はmyListに設定してある個数、 チェックボックスのラベルはmyListに設定してある値で画面に表示されます。
また、Submitボタンを一つ配置しています。フォームのアクションがPOSTであり、asp-page-handler="Action" が指定されているため、ボタンクリック時には、ページモデルクラスの OnPostAction()メソッドが実行されます。
  <form method="post">
    @{
      for (int i=0; i<Model.myList.Count; i++){
        <div><input id="checkbox_@Model.myList[i].Id" type="checkbox" asp-for="CheckBoxChecked![i]" /><label for="checkbox_@Model.myList[i].Id">@Model.myList[i].Name</label></div>
      }
    }
    <input type="submit" ID="Button1" value="Exec" class="FormButton" asp-page-handler="Action" />
  </form>

ページの下部には結果を表示するための、OutMessageプロパティの出力枠を記述しています。
  @Html.Raw(Model.OutMessage)

/Pages/Checkbox1.cshtml.cs

チェックボックスの情報を保持するMyItemクラスを定義します。今回はIdとNameのプロパティを定義しています。
    public class MyItem
    {
      public int Id { get; set; }
      public string Name { get; set; } = "";
    }

複数のチェックボックスの情報を格納するため、MyItemオブジェクトのリストを用意します。
    public List<MyItem> myList = new List<MyItem>();

チェックボックスのクリック状態を格納する、bool型の配列を準備します。
    [BindProperty]
    public bool[]? CheckBoxChecked { get; set; }

画面に結果を出力するためのプロパティです。
    [BindProperty]
    public string OutMessage { get; set; } = "";

ページの表示時には、OnGetメソッドが呼び出され、CreateList() メソッドを呼び出します。
    public void OnGet()
    {
      CreateList();
    }

CreateList() メソッドでは、MyItemオブジェクトを複数作成し、myListオブジェクトに追加しています。
    private void CreateList()
    {
      myList.Add(new MyItem { Id = 200, Name = "ぺんぎんクッキー" });
      myList.Add(new MyItem { Id = 201, Name = "しろくまアイス" });
      myList.Add(new MyItem { Id = 202, Name = "かるがもサブレ" });
      myList.Add(new MyItem { Id = 203, Name = "らくだキャラメル" });
      myList.Add(new MyItem { Id = 204, Name = "くじらケーキ" });
      myList.Add(new MyItem { Id = 205, Name = "かぴばらタルト" });
    }

ページのボタンがクリックされると、下記のOnPostAction()イベントが呼び出されます。
CheckBoxCheckedプロパティの要素を1つずつ確認し、trueである項目がクリックされているチェックボックスと判定し、画面にメッセージを表示します。
    public void OnPostAction()
    {
        for (int i=0; i < CheckBoxChecked!.Length; i++)
        {
          if (CheckBoxChecked[i] == true)
          {
            OutMessage += string.Format("<p>{0:d}のチェックボックスがチェックされています。</p>",i);
          }
        }
    }

実行結果

プロジェクトを実行します。下図のページが表示されます。


チェックボックスをクリックし、ページ下部の[Exec]ボタンをクリックします。


ボタンをクリックすると下図の画面に切り替わります。チェックしたチェックボックスの順番が画面に表示されます。


この方法ではチェックボックスの順番はわかりますが、対応するチェックボックスの情報はわからないため、実際に利用する場合はもう少し工夫が必要です。

プログラム例2: チェック情報をチェックボックスの情報と合わせて格納する例 (正しく動作しません)

先のコードではチェックされたチェックボックスの順番は検出できるものの、チェックボックスの情報との対応付けができないため、実用的ではありません。 チェックボックスの情報と、チェックボックスのチェック状態を同時に管理すれば、対応付けができるため、次のコードを記述します。

コード

/Pages/Checkbox2.cshtml
@page
@model DynamicCheckboxCore.Pages.Checkbox2Model
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
  <head>

  </head>
  <body>
    <h2>動的なチェックボックスのデモ</h2>

  <form method="post">
    @{
      for (int i=0; i<Model.CheckBoxList!.Length; i++){
        <div><input id="checkbox_@Model.CheckBoxList![i].Id" type="checkbox" asp-for="CheckBoxList[i].Checked" /><label for="checkbox_@Model.CheckBoxList![i].Id">@Model.CheckBoxList![i].Name</label></div>
      }
    }
    <input type="submit" ID="Button1" value="Exec" class="FormButton" asp-page-handler="Action" />
  </form>

  @Html.Raw(Model.OutMessage)

  </body>
</html>
/Pages/Checkbox2.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DynamicCheckboxCore.Pages
{
  public class Checkbox2Model : PageModel
  {
    public class CheckBoxInfo
    {
      public int Id { get; set; }
      public string Name { get; set; } = "";
      public bool Checked { get; set; }
    }

    [BindProperty]
    public CheckBoxInfo[]? CheckBoxList { get; set; }

    [BindProperty]
    public string OutMessage { get; set; } = "";

    public void OnGet()
    {
      CreateList();
    }

    public void OnPostAction()
    {
        foreach (CheckBoxInfo ci in CheckBoxList!)
        {
          if (ci.Checked == true)
          {
            OutMessage += string.Format("<p>{0:d}:{1}がチェックされています。</p>", ci.Id, ci.Name);
          }
        }
    }

    private void CreateList()
    {
      List<CheckBoxInfo> myList = new List<CheckBoxInfo>();
      
      myList.Add(new CheckBoxInfo { Id = 200, Name = "ぺんぎんクッキー" });
      myList.Add(new CheckBoxInfo { Id = 201, Name = "しろくまアイス" });
      myList.Add(new CheckBoxInfo { Id = 202, Name = "かるがもサブレ" });
      myList.Add(new CheckBoxInfo { Id = 203, Name = "らくだキャラメル" });
      myList.Add(new CheckBoxInfo { Id = 204, Name = "くじらケーキ" });
      myList.Add(new CheckBoxInfo { Id = 205, Name = "かぴばらタルト" });

      CheckBoxList = myList.ToArray();
    }
  }
}

解説

/Pages/Checkbox2.cshtml

RazoePageでは、CheckBoxList 配列の要素をループで1つずつ取得しチェックボックスをページに配置します。
チェックボックスのラベルはCheckBoxListCheckBoxInfo 要素のNameプロパティの値を設定します。 asp-for="CheckBoxList[i].Checked" を指定することで、CheckBoxListオブジェクトの対応するチェックボックスのCheckedプロパティにチェックボックスのチェック状態を反映させます。
    @{
      for (int i=0; i<Model.CheckBoxList!.Length; i++){
        <div><input id="checkbox_@Model.CheckBoxList![i].Id" type="checkbox" asp-for="CheckBoxList[i].Checked" /><label for="checkbox_@Model.CheckBoxList![i].Id">@Model.CheckBoxList![i].Name</label></div>
      }
    }

先の例と同様の処理を実行するSubmitボタンを配置します。 フォームのアクションがPOSTであり、asp-page-handler="Action" が指定されているため、ボタンクリック時には、ページモデルクラスの OnPostAction()メソッドが実行されます。
    <input type="submit" ID="Button1" value="Exec" class="FormButton" asp-page-handler="Action" />

ページの下部には結果を表示するための、OutMessageプロパティの出力枠を記述しています。
  @Html.Raw(Model.OutMessage)

/Pages/Checkbox2.cshtml.cs

チェックボックスの情報を格納するCheckBoxInfo オブジェクトと、CheckBoxInfoオブジェクトを複数格納するCheckBoxListプロパティを宣言します。
    public class CheckBoxInfo
    {
      public int Id { get; set; }
      public string Name { get; set; } = "";
      public bool Checked { get; set; }
    }
    [BindProperty]
    public CheckBoxInfo[]? CheckBoxList { get; set; }

ページ表示時に呼び出されるOnGetメソッドでチェックボックスの情報を格納するmyListプロパティの値を作成します。 プロパティは配列型で定義されているため、List<CheckBoxInfo> オブジェクトを作成後 ToArray() メソッドを利用して配列に変換します。
    public void OnGet()
    {
      CreateList();
    }
    private void CreateList()
    {
      List<CheckBoxInfo> myList = new List<CheckBoxInfo>();
      
      myList.Add(new CheckBoxInfo { Id = 200, Name = "ぺんぎんクッキー" });
      myList.Add(new CheckBoxInfo { Id = 201, Name = "しろくまアイス" });
      myList.Add(new CheckBoxInfo { Id = 202, Name = "かるがもサブレ" });
      myList.Add(new CheckBoxInfo { Id = 203, Name = "らくだキャラメル" });
      myList.Add(new CheckBoxInfo { Id = 204, Name = "くじらケーキ" });
      myList.Add(new CheckBoxInfo { Id = 205, Name = "かぴばらタルト" });

      CheckBoxList = myList.ToArray();
    }

画面に出力するOutMessageプロパティを宣言します。
    [BindProperty]
    public string OutMessage { get; set; } = "";

ボタンをクリックした際には下記のOnPostAction()メソッドが実行されます。 CheckBoxList の要素をループで取得し、Checkedプロパティがtrueの場合にチェックされている旨のメッセージを表示します。
    public void OnPostAction()
    {
        foreach (CheckBoxInfo ci in CheckBoxList!)
        {
          if (ci.Checked == true)
          {
            OutMessage += string.Format("<p>{0:d}:{1}がチェックされています。</p>", ci.Id, ci.Name);
          }
        }
    }

実行結果

プロジェクトを実行します。Webブラウザが起動しますので、作成したページを表示します。
下図のページが表示されます。


チェックボックスをクリックしてチェックをつけます。チェック後、ページ下部の[Exec]ボタンをクリックします。


ボタンをクリックすると下図のページが表示されます。チェックされている項目の個数は一致していますが、IDはすべて0となり、Nameも空の文字列となっています。


デバッグで、OnPostActionイベント内でのCheckBoxListプロパティの内容を確認します。 Checkプロパティにチェックボックスのチェック状態は反映されていますが、IDやNameの値は初期値の状態となっています。asp-forで指定した値以外はページのPOSTでは引き継がれず、 再度CreateListイベントにより設定しないと値は設定されない動作です。

プログラム例3: hiddenフィールドを利用する例

先のプログラムでは、チェック状態は取得できていましたが、他のチェックボックスの情報がPOST後に引き継がれない問題がありました。 POST時にチェックボックスの値を引き継ぐために、hiddenフィールドにチェックボックスの情報を設定し、asp-for属性に値を設定してPOSTされた際に値が渡されるように実装します。

コード

RazorPageを作成し、以下のコードを作成します。
/Pages/Checkbox3.cshtml
@page
@model DynamicCheckboxCore.Pages.Checkbox3Model
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
  <head>

  </head>
  <body>
    <h2>動的なチェックボックスのデモ</h2>

  <form method="post">
    @{
      for (int i=0; i<Model.CheckBoxList!.Length; i++){
        <div><input id="checkbox_@Model.CheckBoxList![i].Id" type="checkbox" asp-for="CheckBoxList[i].Checked" /><label for="checkbox_@Model.CheckBoxList![i].Id">@Model.CheckBoxList![i].Name</label></div>
        <input type="hidden" asp-for="CheckBoxList![i].Id" />
        <input type="hidden" asp-for="CheckBoxList![i]!.Name" />
      }
    }
    <input type="submit" ID="Button1" value="Exec" class="FormButton" asp-page-handler="Action" />

  </form>

  @Html.Raw(Model.OutMessage)

  </body>
</html>
/Pages/Checkbox3.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DynamicCheckboxCore.Pages
{
  public class Checkbox3Model : PageModel
  {
    public class CheckBoxInfo
    {
      public int Id { get; set; }
      public string Name { get; set; } = "";
      public bool Checked { get; set; }
    }

    [BindProperty]
    public CheckBoxInfo[]? CheckBoxList { get; set; }

    [BindProperty]
    public string OutMessage { get; set; } = "";


    public void OnGet()
    {
      CreateList();
    }

    public void OnPostAction()
    {
      foreach (CheckBoxInfo ci in CheckBoxList!)
      {
        if (ci.Checked == true)
        {
          OutMessage += string.Format("<p>{0:d}:{1}がチェックされています。</p>", ci.Id, ci.Name);
        }
      }
    }

    private void CreateList()
    {
      List<CheckBoxInfo> myList = new List<CheckBoxInfo>();

      myList.Add(new CheckBoxInfo { Id = 200, Name = "ぺんぎんクッキー" });
      myList.Add(new CheckBoxInfo { Id = 201, Name = "しろくまアイス" });
      myList.Add(new CheckBoxInfo { Id = 202, Name = "かるがもサブレ" });
      myList.Add(new CheckBoxInfo { Id = 203, Name = "らくだキャラメル" });
      myList.Add(new CheckBoxInfo { Id = 204, Name = "くじらケーキ" });
      myList.Add(new CheckBoxInfo { Id = 205, Name = "かぴばらタルト" });

      CheckBoxList = myList.ToArray();
    }
  }
}

解説

/Pages/Checkbox3.cshtml

先ほどのコードと同様ですが、input type="hidden" タグを追加しています。asp-for に値を設定することでPOST時に値が反映される動作にします。
    @{
      for (int i=0; i<Model.CheckBoxList!.Length; i++){
        <div><input id="checkbox_@Model.CheckBoxList![i].Id" type="checkbox" asp-for="CheckBoxList[i].Checked" /><label for="checkbox_@Model.CheckBoxList![i].Id">@Model.CheckBoxList![i].Name</label></div>
        <input type="hidden" asp-for="CheckBoxList![i].Id" />
        <input type="hidden" asp-for="CheckBoxList![i]!.Name" />
      }

/Pages/Checkbox3.cshtml.cs

先ほどの例のCheckbox2.cshtml.cs と同じコードです。

実行結果

プロジェクトを実行します。Webブラウザが起動しますので、作成したRazorPageを表示します。


チェックボックスをクリックしてチェックをつけます。チェック後、[Exec]ボタンをクリックします。


ボタンをクリックすると下図の表示に切り替わります。画面にチェックされたチェックボックスのIDとチェックボックスの名称が表示されます。


動的に複数のチェックボックスを生成してチェックされたチェックボックスの項目の情報を取得できました。

プログラム例4: POST時に再度情報を代入する方法

別の実装としてPOST時に再度情報を代入する方法があります。
ページ表示時のGET時とPOST時で順番を一致させる必要があるため、あまり効率の良い実装方法ではありません。

コード

/Pages/Checkbox4.cshtml
@page
@model DynamicCheckboxCore.Pages.Checkbox4Model
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
</head>
<body>
  <h2>動的なチェックボックスのデモ</h2>

  <form method="post">
    @{
      for (int i = 0; i < Model.CheckBoxList!.Length; i++)
      {
        <div><input id="checkbox_@Model.CheckBoxList![i].Id" type="checkbox" asp-for="CheckBoxList[i].Checked" /><label for="checkbox_@Model.CheckBoxList![i].Id">@Model.CheckBoxList![i].Name</label></div>
      }
    }
    <input type="submit" ID="Button1" value="Exec" class="FormButton" asp-page-handler="Action" />
  </form>
  @Html.Raw(Model.OutMessage)
</body>
</html>
/Pages/Checkbox4.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DynamicCheckboxCore.Pages
{
  public class Checkbox4Model : PageModel
  {
    public class CheckBoxInfo
    {
      public int Id { get; set; }
      public string Name { get; set; } = "";
      public bool Checked { get; set; }
    }

    [BindProperty]
    public CheckBoxInfo[]? CheckBoxList { get; set; }

    [BindProperty]
    public string OutMessage { get; set; } = "";

    public void OnGet()
    {
      CreateList(false);
    }

    public void OnPostAction()
    {
      CreateList(true);

      foreach (CheckBoxInfo ci in CheckBoxList!)
      {
        if (ci.Checked == true)
        {
          OutMessage += string.Format("<p>{0:d}:{1}がチェックされています。</p>", ci.Id, ci.Name);
        }
      }
    }

    private void CreateList(bool FillInfo)
    {
      if (FillInfo == true)
      {
        CheckBoxList[0].Id = 200;
        CheckBoxList[0].Name = "ぺんぎんクッキー";

        CheckBoxList[1].Id = 201;
        CheckBoxList[1].Name = "しろくまアイス";

        CheckBoxList[2].Id = 202;
        CheckBoxList[2].Name = "かるがもサブレ";

        CheckBoxList[3].Id = 203;
        CheckBoxList[3].Name = "らくだキャラメル";

        CheckBoxList[4].Id = 204;
        CheckBoxList[4].Name = "くじらケーキ";

        CheckBoxList[5].Id = 205;
        CheckBoxList[5].Name = "かぴばらタルト";
      }
      else
      {
        CheckBoxList = new CheckBoxInfo[6];
        CheckBoxList[0] = new CheckBoxInfo { Id = 200, Name = "ぺんぎんクッキー" };
        CheckBoxList[1] = new CheckBoxInfo { Id = 201, Name = "しろくまアイス" };
        CheckBoxList[2] = new CheckBoxInfo { Id = 202, Name = "かるがもサブレ" };
        CheckBoxList[3] = new CheckBoxInfo { Id = 203, Name = "らくだキャラメル" };
        CheckBoxList[4] = new CheckBoxInfo { Id = 204, Name = "くじらケーキ" };
        CheckBoxList[5] = new CheckBoxInfo { Id = 205, Name = "かぴばらタルト" };
      }
    }
  }
}

解説

hiddenフィールドのinputを利用せずに、POST後にCheckBoxInfoに再度情報を挿入することでチェックしたチェックボックスとチェックボックスの情報を対応付ける実装方法です。
CreateListメソッドを下記のコードで実装します。第一引数がfalseの場合は、CheckBoxInfoオブジェクトを作成しCheckBoxListに挿入します。 第一引数がfalseの場合はPOSTでアクセスされすでに、CheckBoxListにオブジェクトが設定されている状態として、各要素のプロパティに値を代入する動作になっています。
    private void CreateList(bool FillInfo)
    {
      if (FillInfo == true)
      {
        CheckBoxList[0].Id = 200;
        CheckBoxList[0].Name = "ぺんぎんクッキー";

        CheckBoxList[1].Id = 201;
        CheckBoxList[1].Name = "しろくまアイス";

        CheckBoxList[2].Id = 202;
        CheckBoxList[2].Name = "かるがもサブレ";

        CheckBoxList[3].Id = 203;
        CheckBoxList[3].Name = "らくだキャラメル";

        CheckBoxList[4].Id = 204;
        CheckBoxList[4].Name = "くじらケーキ";

        CheckBoxList[5].Id = 205;
        CheckBoxList[5].Name = "かぴばらタルト";
      }
      else
      {
        CheckBoxList = new CheckBoxInfo[6];
        CheckBoxList[0] = new CheckBoxInfo { Id = 200, Name = "ぺんぎんクッキー" };
        CheckBoxList[1] = new CheckBoxInfo { Id = 201, Name = "しろくまアイス" };
        CheckBoxList[2] = new CheckBoxInfo { Id = 202, Name = "かるがもサブレ" };
        CheckBoxList[3] = new CheckBoxInfo { Id = 203, Name = "らくだキャラメル" };
        CheckBoxList[4] = new CheckBoxInfo { Id = 204, Name = "くじらケーキ" };
        CheckBoxList[5] = new CheckBoxInfo { Id = 205, Name = "かぴばらタルト" };
      }
    }

他のコードについてはプログラム例2のコードと同様です。

実行結果

プロジェクトを実行します。Webブラウザが起動しますので、作成したRazorPageを表示します。


チェックボックスをクリックしてチェックをつけます。チェック後、[Exec]ボタンをクリックします。


ボタンをクリックすると下図の表示に切り替わります。画面にチェックされたチェックボックスのIDとチェックボックスの名称が表示されます。

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