2010-07-28 22 views
5

我有这个在ASP.NET MVC视图中填充下拉列表。ASP.NET MVC:DropDownListFor不选择任何选项

<%= Html.DropDownListFor(model => model.Bikes, 
     Model.Bikes.Select(
     x => new SelectListItem { 
       Text = x.Name, 
       Value = Url.Action("Details", "Bike", new { bikeId = x.ID }), 
       Selected = x.ID == Model.ID, 
      })) %> 

调试这个我可以看到Selected属性设置为true当它应该是。但是,当渲染视图时,列表中的选项都未被选中。我意识到这可以通过DropDownListFor的另一个重载来完成,但我真的想让这个版本工作。

任何想法?

回答

5

您选择的值不起作用的原因是因为您将Url用作选项值,但在 Selected子句中指定了 Model.ID

尝试这样的:

<%= Html.DropDownListFor(
    model => model.Bikes, 
    new SelectList(Model.Bikes, "Id", "Name", Model.ID) 
)%> 

"Id"表示将用作选项值的属性,而"Name"表示将用作选项标签的属性。

如果你想保留Url.Action你可以尝试:

​​

你会发现,我倒的名称和ID,因为它似乎更符合逻辑使用模型ID作为选项值。


UPDATE:

这不工作的原因是因为你绑定到一个IEnumerable(该DropDownListFor助手的第一个参数)。当您使用相同model.Bikes收集这应该是一个标量属性:

<%= Html.DropDownListFor(
    model => model.SelectedBikeValue, 
    Model.Bikes.Select(
     x => new SelectListItem { 
       Text = x.Name, 
       Value = Url.Action("Details", "Bike", new { bikeId = x.ID }), 
       Selected = x.ID == Model.ID, 
     } 
)) %> 

我对作为选项值代表真不使用URL的话。

+0

请注意,在我原来的问题中,值是URL。 – 2010-07-28 11:35:26

+1

是的,我注意到了这一点,但是因为这对我来说似乎是一个糟糕的主意,我倒过来了。顺便说一下,这就是为什么你选择的值不起作用。您将Model.Id作为选定值传递,并使用URL作为选项值。不好。我建议您将ID保留为选项值,如有必要,请在您要提交的控制器操作中获取相应的URL。我不认为合理使用网址作为选项值。 – 2010-07-28 11:39:02

+0

在我的原始代码中,我不会将ID作为选项值和URL作为选项值传递。我正在做的是将值设置为URL,然后使用应该适用于要选择的项目的条件。是否真的有什么令人信服的理由,为什么我不应该使用URL的值? – 2010-07-28 11:46:50

0

我对这个概念有太多的麻烦。当你不能通过它时,它会特别显现出来。“name”属性来自包含该对象属性的模型,因为这样的对象名称会自动添加到名称中。这太疯狂了。在浪费了很多时间试图想出这个问题之后,我放弃了,写下了我自己在这里发布的下拉式扩展。它非常简单,而且工作得很好。

public static MvcHtmlString SimpleDropDown(this HtmlHelper helper, object attributes, IEnumerable<SelectListItem> items, bool disabled = false) 
    { 
     XElement e = new XElement("select", 
      items.Select(a => { 
       XElement option = new XElement("option", a.Text); 
       option.SetAttributeValue("value", a.Value); 
       if (a.Selected) 
        option.SetAttributeValue("selected", "selected"); 
       return option; 
      }) 
      ); 

     if (attributes != null) 
     { 
      Dictionary<string, string> values = (from x in attributes.GetType().GetProperties() select x).ToDictionary(x => x.Name, x => (x.GetGetMethod().Invoke(attributes, null) == null ? "" : x.GetGetMethod().Invoke(attributes, null).ToString())); 
      foreach(var v in values) 
       e.SetAttributeValue(v.Key, v.Value); 
     } 

     if (disabled) 
      e.SetAttributeValue("disabled", ""); 

     return new MvcHtmlString(e.ToString()); 
    } 

而且,我把标志禁用作为一个额外的参数,因为如果你想通过属性的标准列表匿名绑定到它,它可以是一个相当麻烦。

下面是我目前如何使用它的一个例子。我将一个字典翻译成一个SelectListItem列表,但它可以只是一个简单的列表。

@Html.SimpleDropDown(new { id="EOM", name = "EOM", @class = "topBox" }, Model.EOM.Select(x => new SelectListItem { Text = x.Value, Value = x.Key.ToString(), Selected = Model.EOM.Selected == x.Key }), !Model.EOM.Available)