LoginSignup
0
0

More than 3 years have passed since last update.

ASP.NET MVCでListBoxFor実行時にselectedが反映されない件について

Posted at

今回のお題

MVCでViewにmultipleなselectを配置するメソッド[HtmlHelper.ListBoxFor<>]。
コイツを使用した際に、デフォルトで選択状態にする(selected属性を付ける)ことができない場合があったので、
備忘録的に書いておきます。

条件

  • モデルに初期値を持っている
  • ListBoxForで使用する選択肢(SelectListItemクラスのリスト)をViewBagに持っている
  • モデルで初期値を持っているプロパティ名と、選択肢を持たせたViewBagのプロパティ名が一致している

発生する問題

ListBoxForによって作成されたselectタグに、モデルで渡したはずの初期値が反映されない。

先に解決策を書いておく

[今回のお題].[条件]を読んでいただいた方にはもう大方の予想はついていると思います。
選択肢を格納しておくViewBagのプロパティ名と、バインド先のModelのプロパティ名が一致していと上手くいかないので、プロパティ名を変更しましょう。

環境

Visual Studio Community 2019 (16.8.3)
Windows10 Pro (2004) 64bit
.NET Framework 4.8

再現するコード

至ってシンプルに書いていきます。

Model

プロパティ[Fruits]だけ持つモデル

BasketVM.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace ListPropertyStudyNET.Models
{
    public class BasketVM
    {
        [Display(Name = "フルーツ")]
        public List<string> Fruits { get; set; }
    }
}

View

モデルの[Fruits]プロパティにバインドし、項目をViewBag.Fruitsから持ってくるListBoxForのみ配置。

Index.cshtml
@model ListPropertyStudyNET.Models.BasketVM
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<div>
    @Html.ListBoxFor(m => m.Fruits, (IEnumerable<SelectListItem>)ViewBag.Fruits, new { @class = "form-control"})
</div>

Controller

ViewBag.Fruitsに選択肢、BasketVM.Fruitsに初期値を設定してIndex.cshtmlを返すだけ。

ShoppingController
using ListPropertyStudyNET.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ListPropertyStudyNET.Controllers
{
    public class ShoppingController : Controller
    {
        // GET: Shopping
        public ActionResult Index()
        {
            //リスト用
            List<SelectListItem> items = new List<SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = "リンゴ",
                    Value = "apple"
                },
                new SelectListItem()
                {
                    Text = "オレンジ",
                    Value = "orange"
                },
                new SelectListItem()
                {
                    Text = "バナナ",
                    Value = "banana"
                }
            };

            //リスト用のプロパティをViewBagに放り込む
            ViewBag.Fruits = items;

            //オレンジとバナナを初期選択にしたい
            BasketVM vm = new BasketVM()
            {
                Fruits = new List<string>()
                {
                    "orange", "banana"
                }
            };

            return View(vm);
        }
    }
}

いざ実行

image.png
image.png
このように、Modelに設定した初期値(オレンジ、バナナの選択)が反映されていません。

コードの修正

Controller

リストの選択肢を設定するViewBagのプロパティ名を変更しています。

ShoppingController.cs
using ListPropertyStudyNET.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ListPropertyStudyNET.Controllers
{
    public class ShoppingController : Controller
    {
        // GET: Shopping
        public ActionResult Index()
        {
            //リスト用
            List<SelectListItem> items = new List<SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = "リンゴ",
                    Value = "apple"
                },
                new SelectListItem()
                {
                    Text = "オレンジ",
                    Value = "orange"
                },
                new SelectListItem()
                {
                    Text = "バナナ",
                    Value = "banana"
                }
            };

            //リスト用のプロパティをViewBagに放り込む
            //ViewBag.Fruits = items;       //※この行を削除して
            ViewBag.FruitsItems = items;    //※この行を追加。ViewBagに設定したプロパティ名が[Fruits → FruitsItems]となりました。

            //オレンジとバナナを初期選択にしたい
            BasketVM vm = new BasketVM()
            {
                Fruits = new List<string>()
                {
                    "orange", "banana"
                }
            };

            return View(vm);
        }
    }
}

View

ViewBagのプロパティ名変更に伴い、コード内で参照するプロパティを変更しています。

Index.cshtml
@model ListPropertyStudyNET.Models.BasketVM
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<div>
    @*@Html.ListBoxFor(m => m.Fruits, (IEnumerable<SelectListItem>)ViewBag.Fruits, new { @class = "form-control"})*@
    @Html.ListBoxFor(m => m.Fruits, (IEnumerable<SelectListItem>)ViewBag.FruitsItems, new { @class = "form-control"})
</div>

再度実行してみる

image.png
image.png
オレンジとバナナに[selected="selected"]が付与されていることがわかります。

まとめ

というわけで、ListBoxForを使用する場合、選択肢を格納しておくViewBagのプロパティ名と、バインド先のModelのプロパティ名が一致している場合、初期選択が反映されないようです。

原因……ご存じの方がいらっしゃったらコメントで教えてください。

以上です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0