SelectListItem selected = true не работает в режиме просмотра
У меня есть поле выбора пола (--Select--, Male, Female), и я заполняю это в своем контроллере. Когда страница загружается, я хочу, чтобы пол, выбранный в модели pm.Gender
, автоматически выбирался при загрузке страницы.
Значения из pm.Gender
возвращаются как:
Вид:
<%: 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;
}
Вы можете сделать это универсальной функцией/расширением "Все включено", но она работает как для меня.