У меня есть этот помощник. Теперь это не мое. Это для отображения и заполнения раскрывающегося списка.
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")
}
Выпадающий рендеринг отлично, но он не выбирает, что должно быть выбрано при загрузке страницы.
Что мне не хватает? Любая помощь приветствуется. благодаря
Ваш вспомогательный метод принимает до 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())
Протестируйте это полностью, поскольку это просто быстрый прототип, чтобы показать вам, как вы можете создать помощника самостоятельно.
Выбранное значение может быть переопределено, если вы используете первый ответ, поскольку свойство Selected
в SelectListItem
будет true
.
@Html.DropDownListFor(model => item.BarId, ViewBag.Bars as IEnumerable<SelectListItem>, "Select bar")
Какое бы значение не было в первом параметре, оно установит выбранное значение для вас. Я не могу сделать что-то, как вы дали, потому что он будет устанавливать только одно и то же значение для всех отображаемых выпадающих.
SelectList
и устанавливает выбранный элемент в списке для вас. Если вы хотите иметь возможность установить значение непосредственно в @Html.DropDownListFor
то вам понадобится помощник, который это делает напрямую.
SelectList
- например,new SelectList(_db.Bars, "BarId ", "BarName")
? И циклforeach
не имеет смысла - создание дублирующих атрибутовid
( недопустимый html) и дубликаты атрибутовname
которые не связаны ни с чем, связанным с вашей моделью.