DropDownListFor в EditorTemplate не выбирает значение - PullRequest
50 голосов
/ 16 декабря 2009

У меня есть шаблон редактора для пользовательского объекта. В этом шаблоне редактора я использую несколько помощников DropDownListFor. В каждом из них я указываю уникальное свойство модели (с предварительно выбранным значением) и список выбора, содержащий все параметры выбора.

Пример:

<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>

Я знаю, что значения параметров заполняются (из источника просмотра) и что моя Модель передается с правильным значением идентификатора (DocumentCategoryType).

Когда представление отображается, в моем раскрывающемся списке нет выбранного элемента, поэтому по умолчанию используется первое (невыбранное) значение.

У кого-нибудь есть идеи?

Спасибо.

Ответы [ 12 ]

28 голосов
/ 04 марта 2010

Мы также решили решение, заполнив новый 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)) %>
18 голосов
/ 11 июня 2010

Просмотр исходного кода ASP.NET MVC 2 показывает некоторые решения этой проблемы. По сути, любой SelectListItem в SelectList, передаваемый в вспомогательном методе расширения, у которого для свойства Selected установлено значение true, не имеет никакого отношения к элементу <option>, отображаемому с атрибутом selected, примененным для элемента.

Атрибут selected в <option> элементах определяется

1) проверка того, что вспомогательный метод расширения был передан SelectList. Если это значение равно null, платформа будет искать в ViewData значение, соответствующее ключу, являющемуся свойством модели представления, для которого вы хотите отобразить раскрывающийся список. Если значение равно SelectList, оно будет использоваться для визуализации <select>, включая принятие любых выбранных значений, при условии, что состояние модели для свойства модели равно нулю.

2) Если в методе расширения помощника передано SelectList, а состояние модели для свойства модели равно нулю, каркас будет искать во 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" }) %>
14 голосов
/ 17 декабря 2009

Это подтверждается как ошибка @ aspnet.codeplex.com и ведет себя так только для строго типизированных представлений.

Обходной путь: заполните свой список выбора в коде представления

как

<%= Html.DropDown("DocumentCategoryType", new SelectList(Model.Categories,"id","Name",Model.SelectedCategory")) =>
6 голосов
/ 18 февраля 2010

Тьфу. В итоге я решил это так. Я надеюсь, что это исправлено для 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) %>
        <%}%>
1 голос
/ 03 февраля 2012

Вот еще одно хорошее решение, если источником вашего выпадающего списка является 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);
}
1 голос
/ 10 марта 2011

Убедитесь, что у вас есть значение, назначенное для m.DocumentCategoryType при отправке его в представление.

Как правило, это значение будет сброшено при повторной публикации, поэтому вам просто нужно указать значение при возвращении к вашему виду.

При создании выпадающего списка вам нужно передать ему два значения. 1. Здесь вы будете хранить выбранное значение 2. Является ли фактический список

Пример

<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>

Я сделал ошибку, установив для элемента списка выбора Выбранное значение значение True. Это ничего не сделает. Вместо этого просто присвойте значение m.DocumentCategoryType в вашем контроллере, и это фактически сделает выбор за вас.

0 голосов
/ 30 сентября 2013

Я беспокоился о производительности создания такого количества копий моего списка выбора, поэтому вместо этого я добавил выбранное значение в качестве пользовательского атрибута, а затем использовал 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")); });
0 голосов
/ 04 июля 2013

Вот раскрывающийся список DropDownList для замены , который незначительно отличается от исходного источника MVC.

Пример:

<%=Html.FixedDropDownListFor(m => m.DocumentCategoryType, 
    Model.DocumentCategoryTypeList) %>
0 голосов
/ 19 июня 2013

У меня тоже была эта проблема с полем ProgramName. Оказывается, мы использовали ViewBag.ProgramName в BaseController и Layout.cshtml, и это было для другой цели. Так как значение в ViewBag.ProgramName не было найдено в раскрывающемся списке, никакое значение не было выбрано, хотя SelectListItem.Selected было true для одного элемента в списке. Мы просто изменили ViewBag, чтобы использовать другой ключ, и проблема была решена.

0 голосов
/ 24 ноября 2010

Скопировано и вставлено из моего проекта:

<%= 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...