2015-04-05 83 views
1

我有这个帮手。现在,这不是我的。这是为了显示和填充下拉菜单。dropdownlistfor未选择页面加载时应该选择什么

public static IEnumerable<SelectListItem> ToSelectList<T, TTextProperty, TValueProperty>(this IEnumerable<T> instance, Func<T, TTextProperty> text, Func<T, TValueProperty> value, Func<T, bool> selectedItem = null) 
     { 
      return instance.Select(t => new SelectListItem 
      { 
       Text = Convert.ToString(text(t)), 
       Value = Convert.ToString(value(t)), 
       Selected = selectedItem != null && selectedItem(t) 
      }); 
     } 

然后,我有这些类:

public class FooVm { 
    public FooVm() { 
    Bars = new HashSet<BarVm>(); 
    } 

    public int FooId { get; set; } 
    public IEnumerable<BarVm> Bars { get; set; } 
} 

public class BarVm { 
    public int BarId { get; set; } 
    public int BarName { get; set; } 
} 

然后有这个LINQ查询:

var fooBar = _db.Foo 
       .WithId(fooId) 
       .Select(f => new FooVm { 
        FooId = f.Id, 
        Bars = f.Bars.Select(b => new BarVm { 
        BarId = b.Id, 
        BarName = b.Name 
        }) 
       }) 
       .ToList(); 

ViewBag.Bars = _db.Bars 
        .ToSelectList(s => s.Name, s => s.Id); 

然后,当我试图使这些结果进行编辑/更新。

@model ViewModels.Foo.FooVm 

@Html.LabelFor(model => model.FooId) 
@foreach(var item in Model.Bars) { 
    @Html.DropDownListFor(model => item.BarId, ViewBag.Bars as IEnumerable<SelectListItem>, "Select bar") 
} 

下拉列表呈现正常,但没有选择页面加载时应该选择的内容。

我错过了什么?任何帮助将非常感激。谢谢

+0

这个帮助器的实际点是什么(与使用'SelectList'构造器之一相反 - 例如'new SelectList(_db.Bars,“BarId”,“BarName”)''而且'foreach'循环没有有道理 - 你会生成重复的'id'属性(无效的html)和重复的'name'属性,这些属性不会绑定到与你的模型相关的任何东西上 – 2015-04-06 02:50:30

+0

@StephenMuecke非常感谢你,不知道我可以做那样的事情。 – 2015-04-06 16:20:57

回答

1

你的帮手方法最多需要3个参数,但你只提供两个参数。第三个参数允许您在默认情况下设置选定的项目,这将是'null'。例如见下文。

ViewBag.Bars = Model.Bars.ToSelectList(s => s.BarName, s => s.BarId, s => s.BarId == 1); 

编辑

试试这个,但因为我不明白你的前提还是你真正想实现这只是东西来指导你。

public static MvcHtmlString DropDownListFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, 
               IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes) 
    { 
     Func<TModel, TValue> method = expression.Compile(); 
     string value = method(helper.ViewData.Model) as string; 

     if (string.IsNullOrEmpty(value) && selectList != null) 
     { 
      var selectListList = selectList.ToList(); 
      var selectedItem = selectListList.FirstOrDefault(s => s.Selected); 
      if (selectedItem == null) 
      { 
       var itemToSelect = selectListList.FirstOrDefault(w => w.Value == selectedValue); 
       if (itemToSelect != null) 
       { 
        itemToSelect.Selected = true; 
       } 
      } 
      return helper.DropDownListFor(expression, selectListList, optionLabel, htmlAttributes); 
     } 

     return helper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes); 
    } 

像这样使用。

@Html.DropDownListFor(model => item, ViewBag.Bars as IEnumerable<SelectListItem>, item.BarId.ToString(), "Select bar", new object()) 

测试这个彻底,因为这只是一个快速的原型,告诉你如何创建自己的帮手。

如果您使用第一个答案,则所选值可被覆盖,因为SelectListItemSelected属性将为true

+0

我以为你可以在剃刀标记中设置选定的值'@ Html.DropDownListFor(model => item.BarId,ViewBag.Bars为IEnumerable ,“Select bar”)'无论值是什么在第一个参数中,它会为你设置选定的值,我不能做你喜欢的东西,因为它只会为所有渲染的下拉菜单设置相同的值。 – 2015-04-05 06:13:46

+0

帮手只是简单地为你提供wi选择一个'SelectList'并在列表中为你选择一个项目。如果你想直接在'@ Html.DropDownListFor'中设置值,那么你需要一个直接做这件事的助手。 – 2015-04-05 06:28:18

+0

在上面的代码中,@ Html.DropDownListFor(model => item.BarId,ViewBag.Bars为IEnumerable ,“Select bar”)'item.BarId'实际上什么也没做。 [您可以简单地传递Item,因为它使用此参数来确定列表绑定到的对象。](https://msdn.microsoft.com/en-us/library/ee703561%28v=vs.118 %29.aspx) – 2015-04-05 06:34:18