DropDownListFor в EditorTemplate не выбирает значение
У меня есть шаблон редактора для настраиваемого объекта. Внутри этого шаблона редактора я использую пару DropDownList для помощников. В каждом из них я указываю уникальное свойство модели (с предварительно выбранным значением) и список выбора, содержащий все параметры выбора.
Пример:
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
Я знаю, что значения параметра заполняются (из источника просмотра) и что моя модель передана с правильным значением ID (DocumentCategoryType).
Когда визуализируется представление, в моем выпадающем списке нет выделенного элемента, поэтому он по умолчанию присваивает первое (не выбранное) значение.
Есть ли у кого-нибудь идеи?
Спасибо.
Ответы
Ответ 1
Тьфу. Я решил это решить. Надеюсь, это будет исправлено для RTM.
<%if(Model!=null){ %>
<%= Html.DropDownListFor(m => m.DocumentCategoryType, new SelectList(Model.DocumentCategoryTypeList,"Value","Text", Model.DocumentCategoryType))%>
<%}else{%>
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
<%}%>
Ответ 2
Мы также решили решение, заполнив новый SelectList
, который имеет соответствующий SelectListItem
выбранный, но создал этот метод расширения, чтобы сохранить код DropDownListFor
немного чище:
public static SelectList MakeSelection(this SelectList list, object selection)
{
return new SelectList(list.Items, list.DataValueField, list.DataTextField, selection);
}
Затем ваш вызов DropDownListFor
будет выглядеть следующим образом:
<%= Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList.MakeSelection(Model.DocumentCategoryType)) %>
Ответ 3
Просматривая исходный код ASP.NET MVC 2, вы обнаружите некоторые решения этой проблемы. По существу, любой SelectListItem
в SelectList
, переданный в методе вспомогательного расширения, который имеет свойство Selected
, установленное в true, не имеет никакого отношения к элементу <option>
, отображаемому с атрибутом Selected
, применяемым к элементу.
Атрибут Selected
на элементах <option>
определяется
1), проверяя, что метод вспомогательного расширения был передан a SelectList
. Если это значение равно null, структура будет выглядеть в ViewData для значения, соответствующего ключу, который является свойством модели представления, для которого вы хотите отобразить выпадающий список. Если значение равно SelectList
, это будет использоваться для отображения <select>
, включающего в себя принятие любых выбранных значений, если состояние модели для свойства модели равно null.
2) Если a SelectList
был передан в методе вспомогательного расширения, а состояние модели для свойства модели равно null, структура будет выглядеть в ViewData для значения по умолчанию, используя имя свойства модели в качестве ключа. Данные в виде данных преобразуются в строку, а любые элементы в SelectList
передаются методу вспомогательного расширения, которые имеют значение (если значение не задано, тогда текст будет проверяться), который соответствует значению по умолчанию, будет иметь Selected
свойство установлено в true, которое в свою очередь будет отображать <option>
с атрибутом selected="selected"
.
Объединяя это, есть два правдоподобных варианта, которые я вижу, чтобы выбрать опцию и использовать строго типизированный DropDownListFor
:
Использование следующей модели представления
public class CategoriesViewModel
{
public string SelectedCategory { get; private set ; }
public ICollection<string> Categories { get; private set; }
public CategoriesViewModel(string selectedCategory, ICollection<string> categories)
{
SelectedCategory = selectedCategory;
Categories = categories;
}
}
Вариант 1
Задайте значение в представлении ViewData в контроллере, отображая ваше представление с именем свойства коллекции, используемой для рендеринга выпадающего меню
действие контроллера
public class CategoriesController
{
[HttpGet]
public ViewResult Select()
{
/* some code that gets data from a datasource to populate the view model */
ICollection<string> categories = repository.getCategoriesForUser();
string selectedCategory = repository.getUsersSelectedCategory();
CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
this.ViewData["Categories"] = selectedCategory;
return View(model);
}
[HttpPost]
public ActionResult Select(CategoriesViewModel model)
{
/* some code that does something */
}
}
и в строго типизированном виде
<%: Html.DropDownListFor(m => m.Categories, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { @class = "my-css-class" }) %>
Вариант 2
Отобразить выпадающее меню с использованием имени свойства выбранного элемента (ов)
действие контроллера
public class CategoriesController
{
[HttpGet]
public ViewResult Select()
{
/* some code that gets data from a datasource to populate the view model */
ICollection<string> categories = repository.getCategoriesForUser();
string selectedCategory = repository.getUsersSelectedCategory();
CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
return View(model);
}
[HttpPost]
public ActionResult Select(CategoriesViewModel model)
{
/* some code that does something */
}
}
и в строго типизированном виде
<%: Html.DropDownListFor(m => m.SelectedCategory, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { @class = "my-css-class" }) %>
Ответ 4
Это подтверждается как ошибка @aspnet.codeplex.com
и ведет себя так же, как для строго типизированных представлений.
Временное решение: заполнить свой SelectList в коде просмотра
как
<%= Html.DropDown("DocumentCategoryType", new SelectList(Model.Categories,"id","Name",Model.SelectedCategory")) =>
Ответ 5
Убедитесь, что вы присваиваете значение m.DocumentCategoryType, когда вы отправляете его в представление.
Как правило, это значение получит reset, когда вы делаете сообщение назад, поэтому вам просто нужно указать значение
при возврате к вашему представлению.
При создании выпадающего списка вам нужно передать два значения. 1. Здесь вы сохраните выбранное значение 2. Является ли фактический список
Пример
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
Я сделал ошибку, установив для элемента списка выбора Selected значение True. Это ничего не сделает. Вместо этого просто назначьте значение m.DocumentCategoryType в своем контроллере, и это действительно сделает выбор для вас.
Ответ 6
Вот еще одно хорошее решение, если источником для раскрывающегося списка является IEnumerable вместо SelectList:
public static SelectList MakeSelection(this IEnumerable<SelectListItem> list, object selection, string dataValueField = "Value", string dataTextField = "Text")
{
return new SelectList(list, dataValueField, dataTextField, selection);
}
Ответ 7
Model.DocumentCategoryTypeList
Это, вероятно, ваша проблема. На SelectListItems вы устанавливаете значение для вывода .ToString()?
var list = new List<SelectListItem>()
{
new SelectListItem()
{
Value = Category.Book.ToString(),
Text = "Book"
},
new SelectListItem()
{
Value = Category.BitsAndPieces.ToString(),
Text = "Bits And Pieces" },
new SelectListItem()
{
Value = Category.Envelope.ToString(),
Text = "Envelopes" }
};
Работает для меня после этого. Он просто должен быть способен сопоставить значение с объектом
Ответ 8
Мне удалось решить ту же проблему, сказав следующее:
new SelectList(sections.Select(s => new { Text = s.SectionName, Value = s.SectionID.ToString() }), "Value", "Text")
Этот трюк преобразуется в значение в строку. Я знаю, что это было упомянуто в предыдущих ответах, но я нахожу свое решение немного чище:). Надеюсь, это поможет.
Ответ 9
Скопировано в мой проект:
<%= Html.DropDownListFor(m => m.Profession.Profession_id, new SelectList(Model.Professions, "Profession_id", "Profession_title"),"-- Profession --")%>
Модель, которая передается:
...
public Profession Profession { get; set; }
public IList<Profession> Professions { get; set; }
...
Сгенерированный HTML:
<select id="Profession_Profession_id" name="Profession.Profession_id">
<option value="">-- Profesion --</option>
<option value="4">Informatico</option>
<option selected="selected" value="5">Administracion</option>
</select>
Работает для меня. У меня есть это в форме, и единственным недостатком является то, что если модель недействительна и я возвращаю модель обратно в представление, мне нужно перезагрузить список профессий.
obj.Professions = ProfileService.GetProfessions();
return View(obj);
Ответ 10
У меня также возникла проблема с полем ProgramName. Оказывается, мы использовали ViewBag.ProgramName в BaseController и Layout.cshtml, и это было для другой цели. Поскольку значение в ViewBag.ProgramName не было найдено в выпадающем списке, значение не было выбрано, хотя SelectListItem.Selected был прав для одного элемента в списке. Мы просто изменили ViewBag, чтобы использовать другой ключ, и проблема была решена.
Ответ 11
Вот вкладка DropDownListFor replacement, которая немного отличается от исходного источника MVC.
Пример:
<%=Html.FixedDropDownListFor(m => m.DocumentCategoryType,
Model.DocumentCategoryTypeList) %>
Ответ 12
Меня беспокоило выполнение множества копий моего selectList, поэтому вместо этого я добавил выбранное значение как пользовательский атрибут, а затем использовал jquery для фактического выполнения выбора элемента:
@Html.DropDownListFor(item => item.AttendeeID, attendeeChoices, String.Empty, new { setselectedvalue = Model.AttendeeID })
........
jQuery("select[setselectedvalue]").each(function () { e = jQuery(this); e.val(e.attr("setselectedvalue")); });