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")); });