【问题标题】:In my asp.net-mvc page, why isn't the right dropdown being selected?在我的 asp.net-mvc 页面中,为什么没有选择正确的下拉菜单?
【发布时间】:2013-08-11 18:26:19
【问题描述】:

我有一个 asp.net-mvc 网站,但我遇到了一个问题,即未选择下拉列表中正确选择的项目。我的控制器操作上有以下代码(简化以隔离问题):

public ActionResult MyAction()
{
 var vm = GetVM();

 var list = new List<INamed> {new NamedInfo() {Id = 1, Name = "Yes"}, new NamedInfo() {Id = 0, Name = "No"}};
 vm.YesNoList = SelectListHelper.GenerateDropdownList(vm.IncludesWeekends ? 1 : 0, list);

  return View(vm);
 }

这里是 GenerateDropdownList 的定义

    public static List<SelectListItem> GenerateDropdownList<T>(int id, IEnumerable<T> list) where T : INamed
    {
        List<SelectListItem> dropdown = list.Select(c => new SelectListItem
        {
            Selected = c.Id == id,
            Text = c.ToString(),
            Value = c.Id.ToString()
        }).ToList();

        return dropdown;
    }

下面是我的 HTML 视图中的代码:

 <% = Html.DropDownList("IncludesWeekends", Model.YesNoList, new { @id = "IncludesWeekends" })%>

我希望在我的示例中选择否(当我在服务器端放置断点时它具有 Selected = true 但是当我查看生成的 html 时,没有选择任何内容:

<select id="IncludesWeekends" class="autoComplete1" name="IncludesWeekends">
 <option value="1">Yes</option>
 <option value="0">No</option>
 </select>

默认选择“是”,因为它是第一项。

关于我在这里做错了什么或可行的替代方案有什么建议吗?

【问题讨论】:

    标签: asp.net-mvc html-select selected selectlistitem


    【解决方案1】:

    SelectListItem 中的Selected 属性大部分是无用的(more about that in my answer here)。在大多数情况下,HTML 助手会忽略它。相反,在您的情况下,他们将查看以下值:

    • ModelState["IncludesWeekends"]
    • ViewData["IncludesWeekends"]
    • Model.IncludesWeekends

    ... 并将他们找到的任何值转换为String,然后将其用作选定值。

    您的模型上有一个 IncludesWeekends 属性,所以它可以:

    Model.IncludesWeekends.ToString()
    

    ...从您的代码来看,这将导致 True" 或 "False"(因为它是 bool)。

    在您的情况下,您使用c.Id.ToString() 作为下拉列表的&lt;option&gt; 值,并且由于帮助程序在这些值(“1”中找不到其选择的字符串(“True”/“False”) "/"0"),它不会选择任何东西。

    解决方法:

    1. (最简单的方法):接受使用“True”和“False”作为&lt;option&gt; 值而不是整数 ID。

    2. (几乎一样简单但不是非常干净的方式):将ViewData["IncludesWeekends"] 设置为您想要选择的值(即Id)。这行得通,因为助手会在Model.IncludesWeekends 之前查看它。

    3. 使用具有IncludesWeekendsId 属性的视图模型,然后使用它来生成下拉列表,而不是IncludesWeekends

      &lt;%= Html.DropDownList("IncludesWeekendsId", Model.YesNoList) %&gt;

      &lt;%= Html.DropDownListFor(m =&gt; m.IncludesWeekendsId, Model.YesNoList) %&gt;

      然后,当从视图返回时,将 IncludesWeekendsId 转换回模型上的正确值。

    在这种情况下,如果我没有学究气,我可能会选择 1。但是解决方案 3 是一种通用的,而且大多是干净的方法来解决这个问题,如果您必须为下拉项使用不同的值而不是转换为字符串的模型属性的值。

    【讨论】:

      【解决方案2】:

      尝试使用 Html.DropDownListFor-helper 代替:

      @Html.DropDownListFor(c => c.Id, Model.YesNoList)
      

      忘记Selected = c.Id == id in:

          List<SelectListItem> dropdown = list.Select(c => new SelectListItem
          {
              Selected = c.Id == id,
              Text = c.ToString(),
              Value = c.Id.ToString()
          }).ToList();
      

      如果可能,发布您的视图模型。

      如果您能够更改,我会推荐使用 Razor 语法,您的视图看起来更清晰! &lt;% Html.DropDown....) %&gt; 变为 @Html.DropDown...)

      【讨论】:

      • 唯一的问题是帮助器中的c.Id 与创建SelectListItem 列表时使用的c.Id 不同。它将是模型的Id(如果它有这样的属性)。
      【解决方案3】:

      如果您为此使用枚举,您的代码会更简洁 我建议您使用这种方法来代替它生成更清晰和一致的代码: https://stackoverflow.com/a/18381045/1654155

      【讨论】:

        【解决方案4】:

        我建议你使用这种类型安全的构造:

        <% = Html.DropDownListFor(x => x.IncludesWeekends, 
                                  new SelectList(Model.YesNoList, "Value", "Text"), 
                                  new { @id = "IncludesWeekends" })%>
        

        而不是这个:

        <% = Html.DropDownList("IncludesWeekends", 
                                Model.YesNoList, 
                                new { @id = "IncludesWeekends" })%>
        

        您获得了很多 - 与给定模型属性相关联的强类型 lambda 表达式,而不是硬编码为魔术字符串的属性名称。使用这种结构,您将自动获得智能感知、重构工具和编译器支持。自 2.0 版本以来,MVC 中存在强类型助手,因此使用旧的没有意义。

        接下来,修改IncludesWeekends 模型值以预选所需的选项。在您的情况下,这意味着将IncludesWeekends 的类型更改为string 而不是bool,并为其分配值"0""1"。或者,如果您不想修改 IncludesWeekends 的类型,请向您的模型添加其他属性,例如SelectedValue 并做一些小改动:

        在行动中:

        vm.SelectedValue = vm.IncludesWeekends ? "1" : "0";
        

        在视图上:

        Html.DropDownListFor(x => x.SelectedValue, ...
        

        您不需要使用 SelectListItemSelected 属性 - 忽略它并删除对它的所有引用。

        【讨论】:

          【解决方案5】:
           public ActionResult Index()
           {
                          ViewModel vm = new ViewModel();
                          vm.IncludesWeekends = false;
                          var list = new List<INamedInfo> { new NamedInfo() { Id = 1, Name = "Yes" }, new NamedInfo() { Id = 0, Name = "No" } };
                          vm.YesNoList = GenerateDropdownList(vm.IncludesWeekends ? 1 : 0, list);
                          vm.IncludesWeekendsValue = vm.IncludesWeekends ? 1 : 0;
                          return View(vm);
           }
          
          
           public class ViewModel
          {
                  public List<SelectListItem> YesNoList { get; set; }
                  public bool IncludesWeekends { get; set; }
                  public int IncludesWeekendsValue { get; set; }
          
          }
          
           <% = Html.DropDownListFor(m => m.IncludesWeekendsValue, Model.YesNoList, new { @id = "IncludesWeekends" })%>
          

          【讨论】:

            猜你喜欢
            • 2015-07-03
            • 1970-01-01
            • 2019-04-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-20
            相关资源
            最近更新 更多