Reputation: 8501
I have this helper. Now, this isn't mine. This is for displaying and populating the dropdown.
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)
});
}
Then I have these classes:
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; }
}
Then having this Linq Query:
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);
Then when I try to render these result for editing/updating.
@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")
}
The dropdown is rendering fine but it isn't selecting of what's supposed to be selected upon page load.
What am I missing? Any help would be much appreciated. Thanks
Upvotes: 1
Views: 774
Reputation: 501
Your helper method takes up to 3 parameter but you are only supplying two. The third parameter allows you to set the selected Item by default this will be 'null'. See below for example.
ViewBag.Bars = Model.Bars.ToSelectList(s => s.BarName, s => s.BarId, s => s.BarId == 1);
EDIT
Try this, but since I don't understand your premise or what you are really trying to achieve this is just something to guide you.
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);
}
Use like this.
@Html.DropDownListFor(model => item, ViewBag.Bars as IEnumerable<SelectListItem>, item.BarId.ToString(), "Select bar", new object())
Test this thoroughly as this is just a quick prototype to show you how you can create the helper on your own.
The selected value can be overridden if you use the first answer as the Selected
property of the SelectListItem
will be true
.
Upvotes: 1