2015-04-05 137 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