10

背景:我的页面上有 4 个下拉列表,它们都使用一个列表来SelectListItem从中提取数据。所有这 4 个下拉菜单中的元素始终完全相同。每个下拉列表的顶部都有一个空元素。

问题:如果我没有从呈现第二个的列表中选择一个项目,当页面加载第二个列表时,会自动选择在第一个列表中选择的项目。这是因为(我认为)列表有一个SelectListItemwhere Selected = true,它只是在第二个列表中使用那个。

有没有办法将一个列表源用于多个下拉列表?我不想重复这个列表 4 次,除非我绝对必须......

代码

//this is the list source
public IEnumerable<SelectListItem> PossibleItems { get; set; }

//this is the code on my .cshtml page
@Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems)
@Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems)
@Html.DropDownListFor(x => x.SelectedItem3, Model.PossibleItems)
@Html.DropDownListFor(x => x.SelectedItem4, Model.PossibleItems)
4

4 回答 4

4

在您的列表中,需要为四个下拉列表中的每一个创建不同的 SelectList 实体,如下所示:

@Html.DropDownListFor(x => x.SelectedItem1, 
    new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem1))
@Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems)
    new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem2))
@Html.DropDownListFor(x => x.SelectedItem3, Model.PossibleItems)
    new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem3))
@Html.DropDownListFor(x => x.SelectedItem4, Model.PossibleItems)
    new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem4))

在此示例中,“dataValue”和“textValue”是 SelectListItem 对象的属性,它们对应于下拉选项的值和文本元素。

于 2013-09-18T19:45:23.427 回答
4

2 年前,但对于像我一样寻找答案的人来说,上面的 Feussy 评论是要走的路。我将尝试解释为什么以及我发现了什么。

使用上面的 OP 示例。必须满足几个条件才能看到所描述的行为。

  • x.SelectedItem1 应该有一个值(比如 1)。
  • x.SelectedItem2 必须为 NULL。(如果它不是可以为空的类型并且只是说一个 INT 它将默认为 0 并且您将看不到该行为)

@Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems)

如果您查看 Model.PossibleItems,您将看到预期的列表。让代码继续到下一行。现在,如果您查看 Model.PossibleItems,您将看到 Html.DropDownListFor 修改了您在模型上的选择列表,而不仅仅是使用它!x.SelectedItem1 的选项现在不仅在发送到客户端的 HTML 中,而且在您的模型中都有一个“selected”属性!这似乎是 Html.DropDownListFor 上的不良行为,但它确实做到了。

现在当你打@Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems)

  • 如果 x.SelectedItem2 有一个值,它会设置它,你会没事的,但是....
  • 如果 x.SelectedItem2 为空,则第二个 @Html.DropDownListFor 似乎只是按原样采用已更改(由第一个 DropDownListFor)选择列表,并且您的第二个下拉菜单将选择 x.SelectedItem1。(因为选择列表本身已更改)

Feussy 的答案有效,因为不是在模型上拥有一个可重用的 selectList,而是创建单独的 selectLists,这些 selectLists 是从模型上的某个 List/IEnumerable 生成的,而该模型上的一些 List/IEnumerable 会被重用。

所以这个故事的寓意是不要重用具有可为空值的 selectList,因为 Html.DropDownListFor 在更改事物时没有问题,并且如果值为 NULL,则不会清除任何选定的属性。

希望这很清楚。

于 2015-11-20T00:34:42.787 回答
3

不要使用 a List<SelectListItem>,而是使用 a SelectList。然后您可以重用DropDownListFor.

模型:

public SelectList PossibleItems { get; set; }

控制器:

var items = new List<SelectListItem>();
model.PossibleItems = new SelectList(items, "Value", "Text");

看法:

@Html.DropDownListFor(m => m.Item1, Model.PossibleItems)
@Html.DropDownListFor(m => m.Item2, Model.PossibleItems)
于 2017-12-15T14:13:00.183 回答
0

您当前拥有的代码是最好的方法,它应该按原样工作。SelectListItem确实有一个Selected属性,但这通常是由一个SelectList实例设置的。否则,您必须自己手动设置此属性。由于您使用的是IEnumerable<SelectListItem>而不是实例化的SelectList,因此所有项目都应默认Selected为 false。只有当 Razor 呈现DropDownListFor控件时,您才能将可枚举变为实际SelectList值并根据模型设置其选定值。检查您的其他代码并确保您没有在任何地方手动设置所选状态。

FWIW,您无需手动添加空项目:DropDownListFor控件具有将空项目添加到列表的方法。

@Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems, string.Empty)
于 2013-09-18T19:46:06.040 回答