DropDownList不尊重SelectList的Selected属性

时间:2013-07-17 05:24:30

标签: c# asp.net-mvc

我有以下代码行:

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

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

输出呈现为:

<option value="0">Past Day</option>
<option value="1">Past Week</option>
<option value="2">Past Month</option>
<option value="3">Past Year</option>
<option value="4">Start of Time</option>

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

Watch list

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

2 个答案:

答案 0 :(得分:22)

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

当你这样做时:

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

... HTML帮助程序将执行其功能而非的所有内容,以使用您在Selected = true中设置为SelectList的值。它会:

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

只有当这两次尝试失败时,它才会屈服,并使用您要求它使用的内容。

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

错误。因为不会将您的财产(enum?)投射到int,就像您一样。它会将其转换为字符串。对于产生枚举名称的enum - 例如PastMonth。如果TimeOption是您的自定义类,那么它将是ToString()的结果。

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

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

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

答案 1 :(得分:2)

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

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

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

注意 - 我不确定Model.TimeOptions的类型是什么 - 如果它不是IEnumerable&lt; TimeOption&GT;然后更换它。 (如果它已经是一个列表,那么.ToList()就没有必要了)