1

3 か国のリストにデータを入力し、デフォルトで 2 番目の項目を選択しようとする単純なコードがあります。何らかの理由で、@Html.DropDownList が画面の 2 番目の項目を初期化していません。誰かがこのコードの問題点を指摘できますか?

public class DemoController : Controller
{
    [HttpGet]
    public ActionResult Test()
    {
        List<SelectListItem> ddlCountries = new List<SelectListItem>();
        SelectListItem item1 = new SelectListItem { Selected = false, Text = "USA", Value = "1" };
        SelectListItem item2 = new SelectListItem { Selected = true, Text = "Ireland", Value = "2" };
        SelectListItem item3 = new SelectListItem { Selected = false, Text = "UK", Value = "3" };

        ddlCountries.Add(item1);
        ddlCountries.Add(item2);
        ddlCountries.Add(item3);

        ViewBag.ddlCountries = ddlCountries;
        return View();
    }

    [HttpPost]
    public string Test(string ddlCountries)
    {
        return "The selected Value was " + ddlCountries;
    }
}

以下は、画面上の出力です。

画面出力

クイックウォッチ ウィンドウは、「選択済み」プロパティが値「2」に正しく設定されていることを示していますが、画面にはこれが反映されていません。

クイックウォッチ出力

ビューのコードは次のとおりです

@{
    ViewBag.Title = "Test";
}

<h2>Test</h2>

@using (Html.BeginForm("Test", "Demo", FormMethod.Post))
{ 

@Html.DropDownList("ddlCountries", (IEnumerable<SelectListItem>) ViewBag.ddlCountries)
    <br />
    <input type="submit" value="submit" />
}
4

1 に答える 1

6

ビュー モデルを使用してみてください。はるかに簡単で、安全で、クリーンです。

public class MyViewModel
{
    public string SelectedCountryId { get; set; }
    public IEnumerable<SelectListItem> Countries { get; set; }
}

そして、コントローラーで:

public class DemoController : Controller
{
    [HttpGet]
    public ActionResult Test()
    {
        List<SelectListItem> ddlCountries = new List<SelectListItem>();
        SelectListItem item1 = new SelectListItem { Text = "USA", Value = "1" };
        SelectListItem item2 = new SelectListItem { Text = "Ireland", Value = "2" };
        SelectListItem item3 = new SelectListItem { Text = "UK", Value = "3" };

        ddlCountries.Add(item1);
        ddlCountries.Add(item2);
        ddlCountries.Add(item3);

        var model = new MyViewModel();
        model.Countries = ddlCountries;
        model.SelectedCountryId = "2"; // preseleted Ireland

        return View(model);
    }

    [HttpPost]
    public ActionResult Test(MyViewModel model)
    {
        return Content("The selected Value was " + model.SelectedCountryId);
    }
}

最後に、強く型付けされたビューで:

@model MyViewModel
@{
    ViewBag.Title = "Test";
}

<h2>Test</h2>

@using (Html.BeginForm("Test", "Demo", FormMethod.Post))
{ 
    @Html.DropDownListFor(x => x.SelectedCountryId, Model.Countries)
    <br />
    <input type="submit" value="submit" />
}

そしてそれはほとんど正しいアプローチです。ViewBag のことは忘れてください。ビューモデルを使用するだけです。ビューの単一の情報源は、ビュー モデルである必要があります。

ちなみに、GET コントローラー アクションは次のように簡略化できます。

[HttpGet]
public ActionResult Test()
{
    var model = new MyViewModel();
    model.Countries = new[]
    {
        new SelectListItem { Text = "USA", Value = "1" },
        new SelectListItem { Text = "Ireland", Value = "2" },
        new SelectListItem { Text = "UK", Value = "3" },
    };
    model.SelectedCountryId = "2"; // preseleted Ireland

    return View(model);
}

または、ビューモデルで国を直接バインドできます。

public class MyViewModel
{
    public string SelectedCountryId { get; set; }
    public IEnumerable<SelectListItem> Countries 
    {
        get
        {
            return new[]
            {
                new SelectListItem { Text = "USA", Value = "1" },
                new SelectListItem { Text = "Ireland", Value = "2" },
                new SelectListItem { Text = "UK", Value = "3" },
            };
        }
    }
}

そして、あなたのコントローラはさらにスリムになります:

public class DemoController : Controller
{
    [HttpGet]
    public ActionResult Test()
    {
        var model = new MyViewModel();
        model.SelectedCountryId = "2"; // preseleted Ireland
        return View(model);
    }

    [HttpPost]
    public ActionResult Test(MyViewModel model)
    {
        return Content("The selected Value was " + model.SelectedCountryId);
    }
}
于 2014-02-09T22:14:17.790 に答える