Si nous ne pensons pas que ce soit un bogue que l'équipe devrait corriger, MSDN devrait au moins améliorer le document. La confusion vient vraiment du mauvais document à ce sujet. Dans MSDN , il explique le nom des paramètres comme suit :
Type: System.String
The name of the form field to return.
Cela signifie simplement que le code HTML final qu'il génère utilisera ce paramètre comme nom de l'entrée sélectionnée. Mais cela signifie en fait plus que cela.
Je suppose que le concepteur suppose que l'utilisateur utilisera un modèle de vue pour afficher la liste déroulante, utilisera également la publication dans le même modèle de vue. Mais dans de nombreux cas, nous ne suivons pas vraiment cette hypothèse.
Utilisez l'exemple ci-dessus,
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
Si nous suivons l'hypothèse, nous devrions définir un modèle de vue pour cette vue associée à la liste déroulante
public class PersonsSelectViewModel{
public string SelectedPersonId,
public List<SelectListItem> Persons;
}
Parce que lors de la publication, seule la valeur sélectionnée sera publiée, elle suppose donc qu'elle doit être renvoyée à la propriété du modèle SelectedPersonId, ce qui signifie que le premier nom de paramètre de Html.DropDownList doit être «SelectedPersonId». Ainsi, le concepteur pense que lors de l'affichage de la vue du modèle dans la vue, la propriété du modèle SelectedPersonId doit contenir la valeur par défaut de cette liste déroulante. Même si votre liste <SelectListItem> Persons a déjà défini l'indicateur Selected pour indiquer lequel est sélectionné / par défaut, le tml.DropDownList l'ignorera et reconstruira son propre IEnumerable <SelectListItem> et définira l'élément par défaut / sélectionné en fonction du nom.
Voici le code de 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);
}
Ainsi, le code est allé plus loin, il essaie non seulement de rechercher le nom dans le modèle, mais également dans les données de vue, dès qu'il en trouve un, il reconstruit la selectList et ignore votre Sélection d'origine.
Le problème est que dans bien des cas, nous ne l'utilisons pas vraiment de cette façon. nous voulons simplement lancer une liste de sélection avec un / plusieurs élément (s) sélectionné (s) défini sur true.
Bien sûr, la solution est simple, utilisez un nom qui ne figure ni dans le modèle ni dans les données de vue. Lorsqu'il ne trouve pas de correspondance, il utilisera la liste de sélection d'origine et la sélection d'origine prendra effet.
Mais je pense toujours que mvc devrait l'améliorer en ajoutant une condition supplémentaire
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
Parce que, si la liste de sélection d'origine en a déjà eu une, pourquoi l'ignoreriez-vous?
Juste mes pensées.