SelectListItem selected = true не работает в режиме просмотра

У меня есть поле выбора пола (--Select--, Male, Female), и я заполняю это в своем контроллере. Когда страница загружается, я хочу, чтобы пол, выбранный в модели pm.Gender, автоматически выбирался при загрузке страницы.

Значения из pm.Gender возвращаются как:

  • ""
  • "M"
  • "F"

Вид:

<%: Model.Gender %>
<%: Html.DropDownListFor(m => m.Gender, (IEnumerable<SelectListItem>)ViewData["gender"], new { @class = "span2" })%>

Контроллер:

gender = new[] { "Select", "Male", "Female" };
List<SelectListItem> genderselectList = new List<SelectListItem>();
foreach (string item in gender)
{
   SelectListItem sli = new SelectListItem { Text = item, Value = item };

   if (item.Trim().StartsWith(pm.Gender))
      sli.Selected = true;

   genderselectList.Add(sli);
}

ViewData["gender"] = genderselectList;

После отладки приложения я вижу, что genderselectList содержит правильные данные с Selected = true для правильного значения, которое должно быть выбрано. Но когда страница загружается, в раскрывающемся списке, который должен был быть сгенерирован с помощью Html.DropDownListFor, ничего не выбрано.

Изменить: Не работает в любом браузере.

Кто-нибудь знает, что может вызвать эту проблему? Любая помощь будет оценена по достоинству.

Приветствия.

EDIT: (После реализации решения Kaf)
Хорошо, так это то, что я делаю после реализации решения Kaf.

Вид:

<%: Html.DropDownListFor(m => m.Gender, (SelectList)(ViewData["gender"]), new { @class = "span2" }) %>

Контроллер:

gender = new[] { "Select", "Male", "Female" };
List<SelectList> genderselectList = new List<SelectList>();
foreach (string item in gender)
{
    SelectList sli;

    if (item.Trim().StartsWith(pm.Gender))
        sli = new SelectList(GetGender(), item, item, item); 
    else
        sli = new SelectList(GetGender(), item, item);
        //without selectedValue

    genderselectList.Add(sli);
}

ViewData["gender"] = genderselectList;

Когда я это делаю, я получаю следующее исключение:
Unable to cast object of type 'System.Collections.Generic.List`1[System.Web.Mvc.SelectList]' to type 'System.Web.Mvc.SelectList'.

Кто-нибудь знает, что я делаю неправильно?

Ответ 1

Я предлагаю это лучше, если вы используете строго типизированное свойство для SelectList (вместо использования ViewBag/ViewData). Я верю, что вы ожидаете, что ваш выпадающий список будет предварительно выбран с учетом гендерного отбора, сделанного в модели. Вот решение (код не на 100% чист, но это будет работать)

Model

public class TestModel
{
    public string Gender { get; set; }

    public IEnumerable<SelectListItem> GenderList
    {
        get
        {
            List<SelectListItem> list = new List<SelectListItem> { new SelectListItem() { Text = "Select", Value = "Select" }, new SelectListItem() { Text = "Male", Value = "Male" }, new SelectListItem() { Text = "Female", Value = "Female" } };
            return list.Select(l => new SelectListItem { Selected = (l.Value == Gender), Text = l.Text, Value = l.Value });
        }
    }
}

Действие контроллера

public ActionResult MyView()
{
    TestModel m = new TestModel();
    m.Gender = "Female";
    return View(m);
}

MyView.cshtml

@model TestModel

@{
    ViewBag.Title = "MyView";
}

<h2>MyView</h2>
@using (Html.BeginForm())
{
    <div>
          @Html.DropDownListFor(model => model.Gender, Model.GenderList)
    </div>
}

OUTPUT

выпадающее меню с выбранной опцией 'Female'

enter image description here

ИЗМЕНИТЬ

Основываясь на комментариях, найдите ниже ссылки на примеры проектов

1) https://github.com/prashanth-t/DropdownDemo_BareBones (с использованием пустого шаблона MVC 4. Меньший размер файла с минимальным размером)

2) https://github.com/prashanth-t/DropdownDemo (с использованием шаблона интернет-приложения MVC 4. Большой размер файла)

Ответ 2

Способ получения полов с помощью select:

private Dictionary<string,string> GetGender(){
    Dictionary<string, string> myDic = new Dictionary<string, string>();
    myDic.Add(System.DBNull.Value.ToString(), "Select");
    myDic.Add("Male", "Male");
    myDic.Add("Female", "Female");
    return myDic;
}

В контроллере:

//without selectedValue
ViewData["gender"]  = new SelectList(GetGender(), "Key", "Value");

ИЛИ

//"Male" as selectedValue
ViewData["gender"]  = new SelectList(GetGender(), "Key", "Value", "Male");

В представлении:

Html.DropDownListFor(m => m.Gender, (SelectList)(ViewData["gender"]),
                        new { @class = "span2" })

Ответ 3

Это известная ошибка в ASP.NET MVC Razor View. В соответствии с известной ошибочной документацией

"Причиной этой проблемы является то, что asp.net MVC сначала ищет совпадение между именем раскрывающегося списка и свойством модели. Если есть совпадение, выбранное значение SelectList переопределяется. Изменение имени отбрасывания вниз это все, что нужно, чтобы решить проблему. "

Я привожу небольшой пример, который вы можете использовать для проверки разрешения.

 var paymentTypeList = new List<SelectListItem>
                {
                    new SelectListItem { Text = "Select Payment Type", Value = "NA" },
                    new SelectListItem { Text = "Card", Value = "Card" },
                    new SelectListItem { Text = "Paytm Wallet", Value = "Paytm Wallet" },
                    new SelectListItem { Text = "Cash", Value = "Cash", Selected = true },
                    new SelectListItem { Text = "Credit", Value = "Credit" },
                    new SelectListItem { Text = "Other", Value = "Other" }
                };
 ViewBag.paymentTypeList = paymentTypeList;

Вариант разрешения 1 (самый простой) - изменить имя объявления идентификатора выбранного списка в представлении MVC, например

@Html.DropDownList("paymentTypeListNew", (List<SelectListItem>)ViewBag.paymentTypeList, new { @class = "form-control select2 select1" })

Решение 2. (Используйте только один конструктор из @Html.DropDownList, который соответствует свойству viewbag/viewdata)

Чтобы убедиться, что выбранный элемент (в данном примере деньги) выбран, выполните следующие действия в MVC Razor View. Используйте только следующий конструктор без CSS или новых значений объекта

 @Html.DropDownList("paymentTypeList") 

Теперь, если вы беспокоитесь, что не можете инициализировать CSS, вам нужно программно инициализировать CSS. Например, если вы используете Jquery, можете ли вы использовать

$("#paymentTypeList").addClass("form-control");
            $("#paymentTypeList").addClass("select2");

Ответ 4

Попробуйте это вместо этого в контроллере:

string[] gender = new string[] {"Male", "Female"};
string selectedGender = gender.Where(x => x.StartsWith(pm.gender)).FirstOrDefault();
ViewData["gender"] = new SelectList(gender, selectedGender);

И в представлении:

<%: Html.Dropdownlist(x => x.Gender, ViewData["gender"], "Select") %>

Ответ 5

Попробуйте это;

public static List<SelectListItem> ListSexo { get; } = new List<SelectListItem>
    {
        new SelectListItem{Selected =true, Value="N", Text="Seleccione"},
        new SelectListItem{Value="F", Text="Femenino"},
        new SelectListItem{Value="M", Text="Masculino"}
    };

<select asp-for="Sexo" asp-items="Commons.ListSexo" class="form-control"></select>

Ответ 6

После поиска себя для ответа на эту проблему - у меня были некоторые подсказки по пути, но это - итоговое решение. Это метод расширения. Я использую MVC 5 С# 4.52 является целью. Приведенный ниже код устанавливает Selection для первого элемента в списке, потому что это то, что мне нужно, вы можете просто пропустить строку и пропустить перечисление - но я также хотел убедиться, что что-то вернулось в мой SelectList из БД)

Extension Method:

public static class SelectListextensions
{

    public static System.Web.Mvc.SelectList SetSelectedValue
(this System.Web.Mvc.SelectList list, string value)
    {
        if (value != null)
        {
            var selected = list.Where(x => x.Text == value).FirstOrDefault();
            selected.Selected = true;                
        }
        return list;
    }    
}

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

Example Code:

SelectList categorylist = new SelectList(dbContext.Categories, "Id", "Name");

SetSelectedItemValue(categorylist);

выберите функцию списка:

private SelectList SetSelectedItemValue(SelectList source)
{
   Category category = new Category();

    SelectListItem firstItem = new SelectListItem();

    int selectListCount = -1;

    if (source != null && source.Items != null)
    {
        System.Collections.IEnumerator cenum = source.Items.GetEnumerator();

        while (cenum.MoveNext())
        {
            if (selectListCount == -1)
            {
                selectListCount = 0;
            }

            selectListCount += 1;

            category = (Category)cenum.Current;

            source.SetSelectedValue(category.Name);

            break;
        }
        if (selectListCount > 0)
        {
            foreach (SelectListItem item in source.Items)
            {
                if (item.Value == cenum.Current.ToString())
                {
                    item.Selected = true;

                    break;
                }
            }
        }
    }
    return source;
}

Вы можете сделать это универсальной функцией/расширением "Все включено", но она работает как для меня.