Если мы не думаем, что это ошибка, которую должна исправить команда, MSDN при аренде должен улучшить документ. Заблуждение действительно исходит из плохого документа об этом. В MSDN объясняются параметры name as,
Type: System.String
The name of the form field to return.
Это просто означает, что конечный html, который он генерирует, будет использовать этот параметр в качестве имени выбранного входа. Но на самом деле это означает нечто большее.
Я предполагаю, что дизайнер предполагает, что пользователь будет использовать модель представления для отображения выпадающего списка, а также будет использовать post обратно в такую же модель представления. Но во многих случаях мы действительно не следуем этому предположению.
Используйте приведенный выше пример,
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 name должен быть 'SelectedPersonId'. Таким образом, дизайнер считает, что при отображении представления модели в представлении свойство модели SelectedPersonId должно содержать значение по умолчанию для этого раскрывающегося списка. Даже если ваш список людей уже установил флаг Selected, чтобы указать, какой из них выбран / по умолчанию, tml.DropDownList фактически проигнорирует это, перестроит свой собственный IEnumerable и установит элемент по умолчанию / выбранный на основе имени.
Вот код из 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);
}
Итак, код на самом деле пошел дальше, он не только пытается найти имя в модели, но также и в данных представления, как только он его находит, он перестраивает список selectList и игнорирует ваш исходный Selected.
Проблема в том, что во многих случаях мы не используем это таким образом. мы просто хотим добавить selectList с одним / несколькими элементами. Выбранный набор true.
Конечно, решение простое, используйте имя, которого нет ни в модели, ни в viewdata. Когда он не может найти совпадение, он будет использовать оригинальный список выбора, и исходный Выбранный вступит в силу.
Но я все еще думаю, что mvc должен улучшить его, добавив еще одно условие
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
Потому что, если в исходном списке selectList уже был один объект Selected, почему бы вам его игнорировать?
Только мои мысли.