Reputation: 44
Im trying to create an dropdownlist from an IList with following syntax:
@Html.DropDowntListFor(Model.VisitingAddresses, vistingAddress => vistingAddress.Id, vistingAddress => vistingAddress.Name)
This works with the following code:
public static IHtmlString DropDowntListFor
<TModel>(this HtmlHelper htmlHelper, IList<TModel> list, Expression<Func<TModel, string>> value, Expression<Func<TModel, string>> text)
{
var dropdownName = value.Parameters.First().Name;
var selectedListItem = new List<SelectListItem>();
var values = list.AsQueryable().Select(value).ToList();
var texts = list.AsQueryable().Select(text).ToList();
int i;
for (i = 0; i < values.Count; i++)
{
selectedListItem.Add(new SelectListItem
{
Value = values[i],
Text = texts[i]
});
}
return htmlHelper.DropDownList(dropdownName, selectedListItem);
}
But as you can see the code above (in the htmlhelper) is really really ugly, is there someone that knows an more beautiful way (in code) for in the html helper?
Thanks in advance.
Upvotes: 3
Views: 1710
Reputation: 1039110
How about the following:
@Html.DropDowntListForVisitingAddress(x => x.Id, x => x.Name)
and then because your view is already strongly typed to some model, HtmlHelper
is already strongly typed => use this to fetch the model:
public static IHtmlString DropDowntListForVisitingAddress(
this HtmlHelper<MyViewModel> html,
Func<VisitingAddress, string> value,
Func<VisitingAddress, string> text
)
{
MyViewModel model = html.ViewData.Model;
var values = model.VisitingAddresses.Select(x => new SelectListItem
{
Value = value(x),
Text = text(x)
});
var selectList = new SelectList(values, "Value", "Text");
return html.DropDownListFor(
x => x.SelectedAddress,
selectList
);
}
Upvotes: 0
Reputation: 1502076
Are you after something like this?
public static IHtmlString DropDowntListFor<TModel>
(this HtmlHelper htmlHelper, IList<TModel> list,
Expression<Func<TModel, string>> valueSelector,
Expression<Func<TModel, string>> textSelector)
{
var dropdownName = valueSelector.Parameters.First().Name;
Func<TModel, string> compiledValueSelector = valueSelector.Compile();
Func<TModel, string> compiledTextSelector = textSelector.Compile();
var selectedListItem = list.Select(x => new SelectListItem {
Value = compiledValueSelector(x),
Text = compiledTextSelector(x) })
.ToList();
return htmlHelper.DropDownList(dropdownName, selectedListItem);
}
Note that if you don't need the text selector as an expression tree, you can simplify it slightly further:
public static IHtmlString DropDowntListFor<TModel>
(this HtmlHelper htmlHelper, IList<TModel> list,
Expression<Func<TModel, string>> valueSelectorExpression,
Func<TModel, string> textSelector)
{
var dropdownName = valueSelector.Parameters.First().Name;
var valueSelector = valueSelectorExpression.Compile();
var selectedListItem = list.Select(x => new SelectListItem {
Value = valueSelector(x),
Text = textSelector(x) })
.ToList();
return htmlHelper.DropDownList(dropdownName, selectedListItem);
}
Upvotes: 4