Якщо ми не вважаємо, що це помилка, яку повинна виправити команда, при оренді MSDN має покращити документ. Плутанина дійсно випливає з поганого документа цього. У MSDN вона пояснює ім'я параметрів як:
Type: System.String
The name of the form field to return.
Це просто означає, що кінцевий html, який він створює, буде використовувати цей параметр як ім'я вхідного вибору. Але це насправді означає більше.
Я думаю, що дизайнер припускає, що користувач використовуватиме модель перегляду для відображення спадного списку, а також буде використовувати повідомлення назад до тієї ж моделі перегляду. Але у багатьох випадках ми насправді не дотримуємось цього припущення.
Скористайтеся наведеним вище прикладом,
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
Якщо ми дотримуємось припущення, нам слід визначити модель подання для цього подання, що пов’язане зі спадним списком
public class PersonsSelectViewModel{
public string SelectedPersonId,
public List<SelectListItem> Persons;
}
Тому що при публікації назад, лише вибране значення буде опубліковано назад, тож передбачається, що воно повинне опублікувати назад у властивості моделі SelectedPersonId, що означає, що перше ім'я параметра Html.DropDownList має бути "SelectedPersonId". Отже, дизайнер вважає, що при відображенні перегляду моделі у поданні, властивість моделі SelectedPersonId має містити значення за замовчуванням цього випадаючого списку. Навіть думав, що ваш список <SelectListItem> Persons вже встановив вибраний прапор, щоб вказати, який з них вибрано / за замовчуванням, tml.DropDownList насправді проігнорує це і відновить власний IEnumerable <SelectListItem> та встановить елемент за замовчуванням / вибраний елемент на основі імені.
Ось код від asp.net mvc
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
{
...
bool usedViewData = false;
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
selectList = htmlHelper.GetSelectData(name);
usedViewData = true;
}
object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));
// If we haven't already used ViewData to get the entire list of items then we need to
// use the ViewData-supplied value before using the parameter-supplied value.
if (defaultValue == null && !String.IsNullOrEmpty(name))
{
if (!usedViewData)
{
defaultValue = htmlHelper.ViewData.Eval(name);
}
else if (metadata != null)
{
defaultValue = metadata.Model;
}
}
if (defaultValue != null)
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
...
return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
}
Таким чином, код фактично пішов далі, він не тільки намагається шукати ім'я в моделі, але і в viewdata, як тільки він знайде його, він відновить selectList і проігнорує ваш вихідний Selected.
Проблема полягає в тому, що у багатьох випадках ми насправді не використовуємо її таким чином. ми просто хочемо ввести список вибору з одним / кількома елементами Вибраний набір вірно.
Звичайно, рішення просте, використовуйте ім’я, яке немає ні в моделі, ні в даних. Коли він не може знайти збіг, він використовуватиме оригінальний список вибору, а оригінал Вибраного вплине на нього.
Але я все ж думаю, що mvc повинен покращити його, додавши ще одну умову
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
Тому що, якщо в оригінальному списку selectList вже був один вибраний, чому б ви його ігнорували?
Просто мої думки.