我注意到在我看来asp.net MVC中的一个错误,或者只是我做错了什么。我目前正在使用1.0,所以这可能会在2.0版本中得到解决。但不管怎样,我们走了。
当我的视图模型具有与下拉列表的声明ID同名的属性时,将忽略所选项目,并且渲染的html没有选择任何内容。 不确定我是否做错了,但更改ID的名称可以解决问题。我简化了这个例子,希望它很清楚,否则请告诉我。
以下是我的观点,其中声明的ID与模型中的列表名称相同:
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<%= Html.DropDownList("IsMultipleServicers", Model.IsMultipleServicers) %>
</td>
</tr>
</table>
呈现的Html
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<select id="IsMultipleServicers" name="IsMultipleServicers">
<option value="false">No</option>
<option value="true">Yes</option>
</select>
</td>
</tr>
</table>
现在让我们做一个小改动。我会将声明的ID更改为不同的内容。
这是我的观点:
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<%= Html.DropDownList("MultipleServicers", Model.IsMultipleServicers) %>
</td>
</tr>
</table>
现在渲染的html:
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<select id="IsMultipleServicers" name="IsMultipleServicers">
<option value="false">No</option>
<option selected="selected" value="true">Yes</option>
</select>
</td>
</tr>
</table>
请注意,现在我得到一个选定的选项,它将是List中的第二个元素。
以下是我的ViewModel,只是将所有内容组合在一起:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCProject.Models.ViewModels.Service
{
public class ServiceViewModel : ViewModel
{
public List<SelectListItem> IsMultipleServicers { get; set; }
}
}
以下是我的行动:
[AcceptVerbs(HttpVerbs.Get)]
public virtual ActionResult Service()
{
return View(new ServiceViewModel()
{
IsMultipleServicers = BuildBooleanSelectList(true)
};
}
private List<SelectListItem> BuildBooleanSelectList(bool isTrue)
{
List<SelectListItem> list = new List<SelectListItem>();
if (isTrue)
{
list.Add(new SelectListItem() { Selected = false, Text = "No", Value = "false" });
list.Add(new SelectListItem() { Selected = true, Text = "Yes", Value = "true" });
}
else
{
list.Add(new SelectListItem() { Selected = true, Text = "No", Value = "false" });
list.Add(new SelectListItem() { Selected = false, Text = "Yes", Value = "true" });
}
return list;
}
答案 0 :(得分:43)
我认为问题是关于DropDownList
重载的混淆:
Html.DropDownList(string name)
查找name
的视图模型属性并输入IEnumerable<SelectListItem>
。它将使用列表中的所选项目(SelectListItem.Selected == true
),除非存在同名的表单发布值。
Html.DropDownList(string name, IEnumerable<SelectListItem> selectList)
使用selectList
中的项目,但不使用其选定的值。通过在视图模型中解析name
(或发布数据)并将其与SelectListItem.Value
进行匹配,可以找到所选内容。即使无法找到该值(或为null),它仍然不会使用SelectListItems列表中的选定值。
您的代码使用第二个重载,但指定了一个不存在的“value”属性(“MultipleServicers”)。
要解决您的问题,请使用第一个重载:
<%= Html.DropDownList("IsMultipleServicers") %>
或者,在视图模型中添加string MultipleServicers
属性并将其填充到控制器中。我推荐这个解决方案,因为它解决了初始显示,后期显示和将后期数据映射到视图/后期模型的几个问题:
public class ServiceViewModel : ViewModel
{
public string MultipleServicers { get; set; }
public List<SelectListItem> IsMultipleServicers { get; set; }
}
然后是你的HTML:
<%= Html.DropDownList(Model.MultipleServicers, Model.IsMultipleServicers) %>
此技术也映射到MVC2:
<%= Html.DropDownListFor(x => x.MultipleServicers, Model.IsMultipleServicers) %>
答案 1 :(得分:9)
我使用Html.DropDownList(字符串名称,IEnumerable selectList)重载遇到了同样的问题。看来我的模型具有与下拉列表名称相同的属性。在这种情况下,MVC偏爱我的Model的属性值而不是IEnumerable中每个条目的Selected属性。
解决方案是使用与属性名称不匹配的下拉列表的名称。另一个解决方案是编写我自己的扩展方法,忽略模型和视图状态,而是始终尊重所选属性。
答案 2 :(得分:2)
DropDownList助手从模型中提取默认值。在第一种情况下,模型中与名称对应的值是SelectList - 这与列表中的任何项都不匹配,它是列表,因此不选择任何值。在第二个示例中,您的模型不包含具有该名称的属性,因此无法使用模型中的值,并且它默认为SelectList本身中指示的状态。通常情况下,我将在模型上为所选值设置一个属性 - 这将成为默认值 - 以及另一个表示列表潜在值的属性。