Как я могу заставить этот ASP.NET MVC SelectList работать?
Я создаю selectList в своем контроллере для отображения в представлении.
Я пытаюсь создать его на лету, что-то вроде этого...
myViewData.PageOptionsDropDown =
new SelectList(new [] {"10", "15", "25", "50", "100", "1000"}, "15");
Он компилируется, но результат плохой...
<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option>10</option>
<option>15</option>
<option>25</option>
<option>50</option>
<option>100</option>
<option>1000</option>
</select>
Обратите внимание, что элемент не выбран?
Как я могу исправить это?
Ответы
Ответ 1
Вот как я это делаю
IList<Customer> customers = repository.GetAll<Customer>();
IEnumerable<SelectListItem> selectList =
from c in customers
select new SelectListItem
{
Selected = (c.CustomerID == invoice.CustomerID),
Text = c.Name,
Value = c.CustomerID.ToString()
};
На второй взгляд я не уверен, что знаю, что вы после...
Ответ 2
Я использую метод расширения:
Использование
var departmentItems = departments.ToSelectList(d => d.Code +
" - " + d.Description,
d => d.Id.ToString(),
" - ");
var functionItems = customerFunctions.ToSelectList(f => f.Description,
f => f.Id.ToString(),
" - ");
с
public static class MCVExtentions
{
public static List<SelectListItem> ToSelectList<T>(
this IEnumerable<T> enumerable,
Func<T, string> text,
Func<T, string> value,
string defaultOption)
{
var items = enumerable.Select(f => new SelectListItem()
{
Text = text(f),
Value = value(f)
}).ToList();
items.Insert(0, new SelectListItem()
{
Text = defaultOption,
Value = "-1"
});
return items;
}
}
Ответ 3
Использование конструктора, который принимает items, dataValueField, dataTextField, selectedValue
в качестве параметров:
ViewData["myList"] =
new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }
.Select(x => new {value = x, text = x}),
"value", "text", "15");
Тогда, на ваш взгляд:
<%=Html.DropDownList("myList") %>
Ответ 4
Создав ответ Thomas Stock, я создал эти перегруженные методы ToSelectList
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
public static partial class Helpers
{
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, bool selectAll = false)
{
return enumerable.ToSelectList(value, value, selectAll);
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, object selectedValue)
{
return enumerable.ToSelectList(value, value, new List<object>() { selectedValue });
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, IEnumerable<object> selectedValues)
{
return enumerable.ToSelectList(value, value, selectedValues);
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, bool selectAll = false)
{
foreach (var f in enumerable.Where(x => x != null))
{
yield return new SelectListItem()
{
Value = value(f).ToString(),
Text = text(f).ToString(),
Selected = selectAll
};
}
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, object selectedValue)
{
return enumerable.ToSelectList(value, text, new List<object>() { selectedValue });
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, IEnumerable<object> selectedValues)
{
var sel = selectedValues != null
? selectedValues.Where(x => x != null).ToList().ConvertAll<string>(x => x.ToString())
: new List<string>();
foreach (var f in enumerable.Where(x => x != null))
{
yield return new SelectListItem()
{
Value = value(f).ToString(),
Text = text(f).ToString(),
Selected = sel.Contains(value(f).ToString())
};
}
}
}
В вашем контроллере вы можете сделать следующее:
var pageOptions = new[] { "10", "15", "25", "50", "100", "1000" };
ViewBag.PageOptions = pageOptions.ToSelectList(o => o, "15" /*selectedValue*/);
И, наконец, в вашем представлении поставьте:
@Html.DropDownList("PageOptionsDropDown", ViewBag.PageOptions as IEnumerable<SelectListItem>, "(Select one)")
Это приведет к желаемому результату - конечно, вы можете оставить опцию "(Select one)"
optionLabel выше, если вы не хотите первый пустой элемент:
<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option value="">(Select one)</option>
<option value="10">10</option>
<option selected="selected" value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="1000">1000</option>
</select>
Обновление: Пересмотренный список кода может быть найден здесь с комментариями XML.
Ответ 5
Проблема заключается в том, что SelectList работает так, как было разработано. Ошибка в дизайне.
Вы можете установить выбранное свойство в SelectedItem, но это полностью игнорируется,
если вы пересекаете список с помощью GetEnumerator() (или если Mvc делает это для вас). Вместо этого Mvc создаст новые элементы SelectListItems.
Вы должны использовать SelectList ctor с помощью SelectListItem [], Text-Name, Value-Name и SelectedValue. Имейте в виду, чтобы передать как SelectedValue значение VALUE из SelectListItem, которое вы хотите выбрать, а не сам SelectListItem!
Пример:
SelectList sl = new SelectList( new[]{
new SelectListItem{ Text="one", Value="1"},
new SelectListItem{ Text="two", Value="2"},
new SelectListItem{ Text="three", Value="3"}
}, "Text", "Value", "2" );
(не проверял это, но у меня была та же проблема)
то второй вариант получит выбранный атрибут = "selected".
Это похоже на старые добрые DataSets; -)
Ответ 6
Это вариант:
myViewData.PageOptionsDropDown = new[]
{
new SelectListItem { Text = "10", Value = "10" },
new SelectListItem { Text = "15", Value = "15", Selected = true }
new SelectListItem { Text = "25", Value = "25" },
new SelectListItem { Text = "50", Value = "50" },
new SelectListItem { Text = "100", Value = "100" },
new SelectListItem { Text = "1000", Value = "1000" },
}
Ответ 7
Если это буквально все, что вы хотите сделать, просто объявив массив как строку, исправляет проблему с выбранным элементом:
myViewData.PageOptionsDropDown =
new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");
Ответ 8
Очень просто заставить SelectList и SelectedValue работать вместе, даже если ваше свойство не является простым объектом, например, Int, String или Double.
Пример:
Предполагая, что наш объект Region выглядит примерно так:
public class Region {
public Guid ID { get; set; }
public Guid Name { get; set; }
}
И ваша модель просмотра выглядит примерно так:
public class ContactViewModel {
public DateTime Date { get; set; }
public Region Region { get; set; }
public List<Region> Regions { get; set; }
}
У вас может быть код ниже:
@Html.DropDownListFor(x => x.Region, new SelectList(Model.Regions, "ID", "Name"))
Только если вы переопределите метод ToString объекта Region на что-то вроде:
public class Region {
public Guid ID { get; set; }
public Guid Name { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
У этого есть гарантия 100% для работы.
Но я действительно считаю, что лучший способ заставить SelectList 100% работать во всех кругах - использовать метод Equals для проверки значения свойства DropDownList или ListBox для каждого элемента коллекции предметов.
Ответ 9
Кажется, что если у вас есть строго типизированное представление, вам нужно изменить идентификатор выпадающего списка, чтобы он не являлся именем свойства в наследуемом классе. Затем вам нужно поместить некоторую логику в свой метод редактирования (POST), чтобы вытащить выбранное значение из FORMCollection и перенести его в свой экземпляр перед выполнением изменений.
Это, конечно, немного странно, но я попробовал, и он работает.
Итак, если у вас класс имеет поле CountryId, и вы показываете список названий стран, сделайте раскрывающийся список с идентификатором CountryName, а не CountryId, а затем в сообщении вы можете сделать что-то с Collection [ CountryName "].
Ответ 10
У меня была такая же проблема. Решение прост. Просто измените параметр "name", переданный помощнику DropDownList, на то, что не соответствует ни одному из свойств, существующих в вашей ViewModel.
подробнее здесь:
http://www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view
Я цитирую Дэна Уотсона:
В MVC, если представление строго типизировано, выбранная опция selectlists будет переопределена, и выбранное свойство свойства, установленное в конструкторе, никогда не достигнет представления, и вместо этого будет выбран первый вариант в раскрывающемся списке (почему все еще немного загадка).
ура!
Ответ 11
Все эти ответы выглядят великолепно, но, похоже, контроллер готовит данные для представления в хорошо известном структурированном формате и позволяет просто перевести IEnumerable < > , поставляемый с помощью модели, и создать стандартный список выбора затем пусть DefaultModelBinder доставляет выбранный элемент обратно вам через параметр действия. Да, нет, почему бы и нет? Разделение проблем, да? Кажется странным иметь контроллер, чтобы создать что-то, поэтому пользовательский интерфейс и вид конкретных.
Ответ 12
Простой:
string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
myViewData.PageOptionsDropDown = new SelectList(someName, "15");
Ответ 13
Используя ваш пример, это сработало для меня:
контроллер:
ViewData["PageOptionsDropDown"] = new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");
Вид:
<%= Html.DropDownList("PageOptionsDropDown")%>
Ответ 14
Я просто запускал его так и не имел проблем,
public class myViewDataObj
{
public SelectList PageOptionsDropDown { get; set; }
}
public ActionResult About()
{
myViewDataObj myViewData = new myViewDataObj();
myViewData.PageOptionsDropDown =
new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");
ViewData["myList"] = myViewData.PageOptionsDropDown;
return View();
}
и
<%=Html.DropDownList("myList") %>
он также работал, если вы это сделаете,
public ActionResult About()
{
myViewDataObj myViewData = new myViewDataObj();
myViewData.PageOptionsDropDown =
new SelectList(new[] { "10", "15", "25", "50", "100", "1000" });
ViewData["myListValues"] = myViewData.PageOptionsDropDown;
ViewData["myList"] = "15";
return View();
}
и
<%=Html.DropDownList("myList",(IEnumerable<SelectListItem>)ViewData["myListValues"]) %>
Ответ 15
MonthRepository monthRepository = new MonthRepository();
IQueryable<MonthEntity> entities = monthRepository.GetAllMonth();
List<MonthEntity> monthEntities = new List<MonthEntity>();
foreach(var r in entities)
{
monthEntities.Add(r);
}
ViewData["Month"] = new SelectList(monthEntities, "MonthID", "Month", "Mars");
Ответ 16
Я делаю это так:
List<SelectListItem> list = new List<SelectListItem>{
new SelectListItem {Selected = true, Text = "Select", Value = "0"},
new SelectListItem {Selected = true, Text = "1", Value = "1"},
new SelectListItem {Selected = true, Text = "2", Value = "2"}
};
return list.ToArray();
ToArray() заботится о проблемах.
Ответ 17
Если вы хотите передать какой-то случайный текст в DropDownList, например - Выбрать -, вы можете легко сделать это, используя этот код:
@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })
Ответ 18
Возможно, у вас есть некоторая двусмысленность в ViewData:
Посмотрите здесь
Ответ 19
значение, выбранное в модели, используется вместо элемента по умолчанию.
(Я согласен, что не читал все сообщения)
Ответ 20
Я не помню, как был настроен mvc 1, но кажется, что он хотел, чтобы список выбора назывался так же, как и поле, в котором оно тоже было...
То, что я нашел, как кто-то сказал выше, заключается в том, что мои списки выбора не работали в mvc2, когда отправляемые ViewData были названы так же, как и поле.
Например:
<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForName"]) %>
работает, когда
<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForID"]) %>
не работает, поскольку имя ViewData "ForID" называется тем же, что и поле, которое оно работает для
Ответ 21
Возможное объяснение заключается в том, что значение selectlist, которое вы связываете, не является строкой.
Итак, в этом примере параметр 'PageOptionsDropDown' - это строка в вашей модели? Потому что, если это не так, то выбранное значение в списке не будет отображаться.
Ответ 22
Если вы посмотрите в исходном коде MVC 2 по методу расширения Html.DropDownList, он никогда не проверяет свойство SelectedValue класса SelectList. Он будет когда-либо пытаться соответствовать вашей модели.
Все вышесказанное представляет собой все варианты темы, то есть как вы отправляете кучу данных в представление для раскрывающегося списка, и все они так же хороши, как и другие (более или менее).
Проблема в представлении. Либо создайте свой собственный метод расширения DropDownList, который будет уважать выбранное значение selectvalue, либо выполнить итерацию вручную. Что всегда лучше для вас.
Ответ 23
Если у вас есть коллекция в вашей модели, и ваш вид сильно напечатан, некоторые варианты этого будут работать:
@Html.DropDownListFor(x => x.RegionID,
new SelectList(Model.Regions,"RegionID", "RegionName", Model.RegionID))
-или -
@Html.DropDownList("RegionID",
new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))