DropDownList不尊重SelectList的Selected属性

我有以下代码行:

@Html.DropDownListFor(x => x.TimeOption, new SelectList(Model.TimeOptions, "Value", "Name", (int)Model.TimeOption)) 

下拉列表已正确构建,并且“选定”确实是正确的,但MVC不会在选择了正确的项目的情况下绘制下拉列表。 标记不会在选项上输出所选属性。

输出呈现为:

 Past Day Past Week Past Month Past Year Start of Time 

然而,如果您查看附加的屏幕截图,您可以看到它已正确选择:

观察清单

这只影响GET,而不影响POST。 想法?

这往往会让人们陷入困境 – 显然MVC 5的路线图包含更直观的DropDownList助手。

当你这样做时:

 @Html.DropDownListFor(x => x.TimeOption ...) 

… HTML帮助程序将尽其所能, 使用您在SelectList设置为Selected = true的值。 它会:

  • 尝试从ModelState获取它 – 它不会获得GET请求
  • 尝试从ViewData获取它 – 它将获得它,因为您的模型上有一个TimeOption属性。

只有当这两种尝试都失败时,它才会屈服,并使用你要求它使用的东西。

因此,在您的情况下,它将使用模型上的TimeOption的当前值作为选定值。 哪个应该没问题,因为那是你在SelectList要求的( (int)Model.TimeOption ),对吧?

错误。 因为它不会像你那样将你的属性( enum ?)转换为int 。 它会将其转换为字符串。 对于产生枚举名称的枚举 – 例如PastMonth 。 如果TimeOption是您的自定义类,则它将是ToString()的结果。

然后,当它没有找到该字符串作为您的值之一时(因为它们都是整数),它决定不进行任何选择。

简而言之: SelectListItem.Selected对帮助程序没有影响。 如果您的帮助程序调用指定了一个名称(字面或通过lambda表达式),则帮助程序将使用ModelStateViewData具有该名称的任何内容,并将其转换为字符串。

在大多数情况下,这会发生在枚举中。 解决它的最简单方法是使用枚举的名称而不是其int表示作为SelectListItem的值。

你上面已经有了一个很好的解释,为什么它不起作用,但只是添加我的2p

通常我更喜欢使用可枚举的SelectListItems作为dropdownitems的来源,尽管两者都应该有效。 这样做更可取,因为不需要指定选择哪个项目 – MVC帮助程序将从值与TimeOption.ToString()方法匹配的那个推断出它。

 @Html.DropDownListFor(x => x.TimeOption, ((IEnumerable)Model.TimeOptions).ToList().ConvertAll(y => new SelectListItem(){Text = y.Name, Value = y.Value.ToString()}) 

注意 – 我不确定Model.TimeOptions在这里是什么类型 – 如果它不是IEnumerable 然后替换它。 (如果它已经是一个列表,则.ToList()不是必需的)