ASPNET MVC DropDownListFor为两个输入重用相同的数据列表会导致意外选择

时间:2016-06-08 20:04:54

标签: asp.net-mvc razor

我创建了以下控制器和视图模型。它允许从同一个选择列表中选择两个用户。

ViewModel和Controller Code

@model Mvc5App.Controllers.FormViewModel

@using (Html.BeginForm("Index", "Form", FormMethod.Post))
{
    <br>
    @Html.LabelFor(m => m.UserSelection1)
    <br>
    @Html.DropDownListFor(m => m.UserSelection1, Model.OptionsSelectList)
    <br>
    @Html.LabelFor(m => m.UserSelection2)
    <br>
    @Html.DropDownListFor(m => m.UserSelection2, Model.OptionsSelectList)
    <br>
}

在剃须刀视图中,您可以看到我正在为DropDownFor帮助器使用相同的列表。

Razor View

uint8_t

问题在于,如果UserSelection1已经有值,则UserSelection2将设置为该值,如果它为null。

选择第一个选择列表项不应该是空值吗?

我是否必须专门将其设置为空字符串以避免这种情况?

3 个答案:

答案 0 :(得分:4)

DropDownListFor()方法在内部构建一个新的IEnumerable<SelectListItem>,以便根据绑定的属性值设置Selected属性的值,但仅限于您绑定的属性不是null

如果是第一个DropDownListFor()UserSelection1),则第3个项目为Selected = true"。它还在ViewDataDictionary

中缓存该集合

如果是第二个DropDownListFor()(对于UserSelection2),则该属性的值为null,因此该方法使用的不是构建新的IEnumerable<SelectListItem>,而是使用ViewData来自viewModel.UserSelection2 = "";的缓存集合,已将第3项设置为已选中。

要了解这一切是如何运作的,您可以查看source code here

您可以通过设置DropDownListFor()的值来正常工作。另请注意,如果您要交换UserSelection2方法的顺序,您会看到您期望的值(即“ - 选择 - ”将选择UserSelection1而“绿色”选择{{1 }})

更好的选择(显示正确的结果)将是使用

FormViewModel viewModel= new FormViewModel()
{
    UserSelection1 = "Green",
    OptionsSelectList = new SelectList(new string[]{ "Red", "Green", "Blue" }),
}
return View(viewModel);

并将属性更改为public IEnumerable<SelectListItem> OptionsSelectList { get; set; },并在视图中使用

@Html.DropDownListFor(m => m.UserSelection1, Model.OptionsSelectList, "- Select -")
@Html.DropDownListFor(m => m.UserSelection2, Model.OptionsSelectList, "- Select- ")

答案 1 :(得分:1)

这种行为是有道理的。想一想......你从同一个OptionSelectList构建你的下拉列表。加载表单视图时,您的下拉列表最初都是使用选定的绿色值构建的。 UserSelection2中的空值表示下拉列表中没有值与之匹配,因此它将保持与第一个值相同的值。

要解决此问题,正如您猜测的那样,您需要将UserSelection2值设置为空字符串,该字符串现在与“请选择”项目匹配,以便选择其中一个。

所以,在Form控制器的Index方法中,只需执行以下操作:

viewModel.UserSelection2 = "";

答案 2 :(得分:0)

对于以后遇到这篇文章的任何人,我发现仅在传递给帮助程序的选择列表上调用ToArray()方法似乎可以解决所有情况。是否为空字符串

@Html.DropDownListFor(m => m.PurchaseTypeId, PurchaseTypeSelectList.ToArray(), new { @class = "form-control" })

当通过ajax请求/ Json响应动态添加表单字段并返回剃刀模板的表单部分时,这就是我最终用来处理int的原因吗?以及下拉列表中的字符串类型值。否则,当将下拉列表添加到dom中(页面加载后)时,它们将选择碰巧选择的内容进行渲染。

为了页面加载,还必须将其添加到我的编辑器模板的顶部:

@{
    Layout = null;
    List<SelectListItem> PurchaseTypeSelectList = ViewBag.PurchaseTypeSelectList ?? new List<SelectListItem>();
    PurchaseTypeSelectList.ForEach(m => m.Selected = false);
}