2013-07-25 1 views
2

J'ai donc un formulaire qui comprend une liste d'éléments, et chaque élément a une liste de sélection. Mon code est comme si (avec des éléments étrangers enlevés):MVC4 Html.DropDownListFor dans une boucle ne définissant pas l'option sélectionnée

@for(var i = 0; i < Model.InputSlots.Count; i++) 
{ 
@Html.DropDownListFor(model => model.InputSlots[i].VariableId, 
     new SelectList(Model.Variables, "VariableId", "Name"), 
     "--Select Variable--", 
     new { @class = "span8" }) 
} 

La liste déroulante affiche correctement, et si je sélectionne l'un des éléments et après la forme, les correctement les messages de sélection, mais quand je charge la page avec VariableId défini sur une option valide, il n'affiche pas l'option sélectionnée, mais affiche la valeur par défaut "--Sélectionnez Variable--" à la place.

J'utilise DropDownListFor à beaucoup d'autres endroits dans mon code, et cela fonctionne comme prévu, mais pas dans ce cas. La seule différence que je peux dire est que c'est référencer une propriété d'un élément de tableau.

J'ai défini un point d'arrêt dans la vue pour vérifier que Model.InputSlots [i] .VariableId est défini sur une option valide (2), et j'ai également consulté le code HTML résultant pour m'assurer qu'il y avait une option avec une valeur de 2 et les deux semblaient corrects, mais il n'y avait pas de "selected" sur l'élément option avec la valeur de 2.

Est-ce un comportement connu, ou suis-je en train de faire quelque chose de mal quelque part que je n'ai pas remarqué?

Mise à jour:

Réglage de l'élément sélectionné dans le constructeur SelectList fonctionne, à savoir:

@Html.DropDownListFor(model => model.InputSlots[i].VariableId, 
     new SelectList(Model.Variables, "VariableId", "Name", Model.InputSlots[i].VariableId), 
     "--Select Variable--", 
     new { @class = "span8" }) 

Mais il ne semble pas vouloir obtenir de l'expression comme dans d'autres cas.

+0

Voir par ex. http: // stackoverflow.com/questions/17691742 et l'une ou l'autre des cinq questions qui y sont liées (ce sont toutes des variations de la même chose). – JimmiTh

+0

Ces liens m'ont rappelé qu'il y avait un argument dans le constructeur de SelectList pour définir l'élément sélectionné, qui fonctionne, mais ils ne traitent pas vraiment la question de savoir pourquoi il ne l'obtient pas de mon lambda comme il est censé. Ma compréhension est que DropDownListFor est vraiment censé ignorer cet argument à moins qu'il ne puisse le comprendre à partir de l'expression. – Gerald

+0

Bien, mal lu la question ... Le problème ici est que tout le helper utilise le lambda pour le traduire en une représentation de chaîne, qu'il utilise pour rechercher les valeurs dans 'ModelState' ou' ViewData'. En d'autres termes, à ce stade, il n'a aucune idée de la valeur de 'i', donc il ne peut pas trouver la valeur de' Model.InputSlots [i] '. – JimmiTh

Répondre

1

Le problème ici est la façon dont tous les assistants DropDown recherchent le defaultValue (qui est toujours un point de douleur).

Quand ils trouvent ModelState (à savoir, lors du retour de la vue d'un POST), ils vont utiliser cela, et votre cas fonctionnera bien, parce que le ModelState a une entrée de dictionnaire nommé InputSlots[0].VariableId.

Lorsqu'il n'y a pas ModelState, cependant, ils vont retomber à ViewData et sa méthode Eval().

Cette méthode va parcourir les données d'affichage pour une clé de dictionnaire InputSlots[0].VariableId - ou une propriété sur le Model portant ce nom (jusqu'à TypeDescriptor.GetProperties()).

Il va également essayer InputSlots[0] - c'est-à-dire trouver une propriété portant ce nom ou une entrée de dictionnaire avec cette clé - puis rechercher une sous-propriété VariableId.

Bien sûr, ni InputSlots[0].VariableId ni InputSlots[0] se trouve, parce qu'il n'y a pas une propriété ou une clé qui comprend [0] en son nom - et Eval() ne faire aucun travail pour analyser les indexeurs - il fonctionne en divisant simplement la chaîne à points (.). En résumé, les helpers - car ils travaillent dans MVC 4 - ne pourront pas trouver automatiquement une valeur par défaut s'il y a un indexeur dans l'expression lambda (ou littéral de chaîne) passé à l'assistant. Je ne peux pas penser à un bien meilleur moyen que de le spécifier vous-même, comme vous le faites dans la mise à jour de la question.

+0

Vous savez, j'ai complètement oublié que MVC était open-source. Après avoir regardé le code, il semble que vous avez raison. J'aurais pensé qu'ils feraient juste d'exécuter l'expression lambda pour obtenir la valeur par défaut, mais apparemment pas. – Gerald

Questions connexes