web-dev-qa-db-fra.com

ASP.NET MVC - Html.DropDownList - Valeur non définie via ViewData.Model

Je viens de commencer à jouer avec ASP.NET MVC et je suis tombé sur la situation suivante. Cela ressemble beaucoup à un bug mais si ce n'est pas le cas, une explication serait appréciée :)

La vue contient des trucs assez basiques

<%=Html.DropDownList("MyList", ViewData["MyListItems"] as SelectList)%>
<%=Html.TextBox("MyTextBox")%>

Lorsque vous n'utilisez pas de modèle, la valeur et l'élément sélectionné sont définis comme prévu:

//works fine
public ActionResult MyAction(){
  ViewData["MyListItems"] = new SelectList(items, "Value", "Text"); //items is an ienumerable of {Value="XXX", Text="YYY"}

  ViewData["MyList"] = "XXX"; //set the selected item to be the one with value 'XXX'
  ViewData["MyTextBox"] = "ABC"; //sets textbox value to 'ABC'

  return View();
}

Mais lorsque vous essayez de charger via un modèle, la zone de texte a la valeur définie comme prévu, mais la liste déroulante n'obtient pas un ensemble d'éléments sélectionné.

//doesnt work
public ActionResult MyAction(){
  ViewData["MyListItems"] = new SelectList(items, "Value", "Text"); //items is an ienumerable of {Value="XXX", Text="YYY"}

  var model = new {
    MyList = "XXX", //set the selected item to be the one with value 'XXX'
    MyTextBox = "ABC" //sets textbox value to 'ABC'
  }

  return View(model);
}

Des idées? Mes pensées actuelles à ce sujet sont que peut-être lors de l'utilisation d'un modèle, nous sommes limités à définir l'élément sélectionné sur le constructeur SelectList au lieu d'utiliser les données de vue (qui fonctionne bien) et de passer la liste de sélection avec le modèle - ce qui aurait l'avantage de nettoyer le code un peu - je me demande juste pourquoi cette méthode ne fonctionne pas ....

Merci beaucoup pour toutes suggestions

17
chrisb

Après un tas d'ourlet et de hachage, cela se résume à la ligne de code suivante

if (ViewData.ModelState.TryGetValue(key, out modelState))

ce qui signifie que MVC essaie de résoudre la valeur en regardant uniquement l'objet ViewData Dictionary <> et non en descendant vers l'objet ViewData.Model.

Que ce soit un bug, une limitation ou une décision de conception, je ne suis pas sûr. Cependant, vous pouvez le corriger de la manière suivante:

<%= Html.TextBox("MyTextBox", ViewData.Model.MyTextBox) %>
5
Todd Smith

En fait, il vous suffit de saisir null pour la Html.DropDownList().
J'avais exactement le même problème et j'ai utilisé le réflecteur pour consulter le code source MVC.

Dans la méthode SelectInternal() de la classe System.Web.Mvc.Extensions.SelectExtensions, Il vérifie si le paramètre selectList est null ou non. S'il est transmis sous la forme null, il recherche correctement le SelectList.

Voici le "Code-behind".

ViewData["MyDropDown"] = new SelectList(selectListItems,
                             "Value",
                             "Text",
                             selectedValue.ToString()
                         );

Voici le code de vue HTML.

<%= Html.DropDownList("MyDropDown", null,
        "** Please Select **",
        new { @class = "my-select-css-class" }
    ) %>

Remarque: j'utilise ASP.NET MVC 2.0 (version bêta).

NOTE DE MISE À JOUR: 31 janvier 2012

Après avoir largement utilisé ASP.NET MVC au cours des 3 dernières années, je préfère utiliser additionalViewData à partir de la fonction Html.EditorFor() méthode plus.

Passez votre [Éléments de liste] en tant qu'objet anonymous avec le même nom de propriété comme propriété du modèle dans la méthode Html.EditorFor().

<%= Html.EditorFor(
    m => m.MyPropertyName,
    new { MyPropertyName = Model.ListItemsForMyPropertyName }
) %>

Si vous voulez plus de détails, veuillez vous référer à ma réponse dans un autre fil ici .

23
stun

essayez de définir la valeur sélectionnée dans l'action du contrôleur lors de la création de la collection SelectList.

ViewData ["AddressTypeId"] = new SelectList (CustomerService.AddressType_List (), "AddressTypeId", "Name", myItem.AddressTypeId);

2
IamNotaRobot

Je suis évidemment en retard ici. Mais je voulais ajouter ce commentaire au cas où quelqu'un d'autre serait tombé sur ce problème.

Dans MVC 2. Vous pouvez procéder comme suit pour sélectionner l'élément ...

public ActionResult Edit(int id)
        {
            Team team = _db.TeamSet.First(m => m.TeamID == id);
            var fanYear = from c in _db.FanYearSet select c;
            ViewData["FantasyYear"] = new SelectList(fanYear, "YearID", "FantasyYear", team.FanYearReference.EntityKey.EntityKeyValues[0].Value);
            var league = from c in _db.LeagueSet select c;
            ViewData["League"] = new SelectList(league, "LeagueID", "League_Name", team.LeaguesReference.EntityKey.EntityKeyValues[0].Value);

            return View(team);
        }

Le quatrième paramètre prend une valeur et sélectionnera la valeur souhaitée dans la liste déroulante. Dans mon exemple, j'ai une table appelée équipe et c'est que j'ai une relation établie avec une table appelée fanYear and league.

Vous pouvez voir que je reçois d'abord l'équipe que je modifie, puis que je crée une liste déroulante d'année fantastique et une autre pour les ligues. Afin de déterminer l'année et la ligue de l'équipe, j'ai dû utiliser la référence d'entité.

Je voulais juste mettre ça là-bas. Je n'ai pu trouver aucun exemple de faire cela.

2
Michael