【问题标题】:MVC Multiple DropDownLists from 1 List<SelectListItem>来自 1 个 List<SelectListItem> 的 MVC 多个 DropDownLists
【发布时间】:2013-09-18 19:28:00
【问题描述】:

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

问题:如果我没有从呈现第二个的列表中选择一个项目,当页面加载第二个列表时,会自动选择在第一个列表中选择的项目。这是因为(我认为)该列表有一个SelectListItem,其中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)

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 html.dropdownlistfor


    【解决方案1】:

    在您的列表中,需要为四个下拉列表中的每一个创建不同的 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 对象的属性,它们对应于下拉选项的值和文本元素。

    【讨论】:

    • 虽然这样做不会有任何伤害,但这不是必需的,也不是问题的根源。
    • 6 年后,您仍在拯救生命!这可能与Model.PossibleItems 已经是SelectListItem 的集合有关,然后SelectListItem.Selected 布尔值在DropDownListFor 之间共享。
    【解决方案2】:

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

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

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

    @Html.DropDownListFor(x =&gt; x.SelectedItem1, Model.PossibleItems)处设置断点

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

    现在当你点击@Html.DropDownListFor(x =&gt; x.SelectedItem2, Model.PossibleItems)

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

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

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

    希望这很清楚。

    【讨论】:

      【解决方案3】:

      不要使用List&lt;SelectListItem&gt;,而是使用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)
      

      【讨论】:

        【解决方案4】:

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

        FWIW,您无需手动添加空项:DropDownListFor 控件可以将空项添加到列表中。

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

        【讨论】:

        • 我没有在其他任何地方设置选定的值,并且我上面的解决方案不起作用,所以我为每个下拉列表使用了单独的列表。不幸的是,它不是最干净的解决方案,但它现在正在工作。
        • 我也面临同样的问题。我同意它应该起作用。但是@gwin003 是对的。这里不对劲。请参阅 this question on asp.net forumsthis question on stackoverflow 了解不满意的回复。
        • 我唯一能想到的可能原因是 Model.PossibleItems 转换为真正的蓝色 SelectList 可能正在缓存并用于每个下拉菜单,因为它们都使用相同的事物。如果您只是将下拉选项复制到另一个属性并将其用于其中一个下拉菜单,会发生什么?是否会发生相同的行为?
        猜你喜欢
        • 1970-01-01
        • 2015-11-08
        • 2011-03-25
        • 2020-10-12
        • 1970-01-01
        • 2020-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多