4

我有一个 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>

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

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

4

5 回答 5

2

in 中的Selected属性SelectListItem大多是无用的(更多关于我的回答在这里)。在大多数情况下,HTML 助手会忽略它。相反,在您的情况下,他们将查看以下值:

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

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

您的模型上有一个IncludesWeekends属性,因此它将执行以下操作:

Model.IncludesWeekends.ToString()

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

在您的情况下,您将c.Id.ToString()其用作下拉列表的<option>值,并且由于助手不会在这些值(“1”/“0”)中找到其选择的字符串(“True”/“False”),因此它赢了不要选择任何东西。

解决方法:

  1. (最简单的方法):接受使用“True”和“False”作为您的<option>值,而不是整数 ID。

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

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

    <%= Html.DropDownList("IncludesWeekendsId", Model.YesNoList) %>

    或者

    <%= Html.DropDownListFor(m => m.IncludesWeekendsId, Model.YesNoList) %>

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

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

于 2013-08-21T20:12:16.803 回答
1

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

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

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

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

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

如果您能够更改,我会推荐使用 Razor 语法,您的视图看起来更干净! <% Html.DropDown....) %>变成@Html.DropDown...)

于 2013-08-11T22:04:32.180 回答
1

如果您使用枚举,您的代码会更干净,我建议您使用这种方法,而不是生成更干净和一致的代码: https ://stackoverflow.com/a/18381045/1654155

于 2013-08-22T13:07:08.807 回答
1

我建议您使用这种类型安全的结构:

<% = 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模型值以预选所需的选项。在您的情况下,这意味着将类型更改为IncludesWeekendstostring而不是bool并为其分配值"0"or "1"。或者,如果您不想修改IncludesWeekends向模型添加附加属性的类型,例如SelectedValue并进行一些小的更改:

在行动中:

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

观点:

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

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

于 2013-08-27T15:06:19.067 回答
0
 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" })%>
于 2013-08-27T13:25:03.933 回答