2010-03-09 9 views
26

J'ai remarqué ce qui me semble un bug dans asp.net MVC ou tout simplement je fais quelque chose de mal. J'utilise actuellement la version 1.0, c'est peut-être quelque chose qui sera traité dans la version 2.0. Mais de toute façon, nous y voilà. Lorsque j'ai mon modèle de vue a une propriété qui est le même nom que l'identificateur déclaré pour une liste déroulante, l'élément sélectionné est ignoré et le html rendu n'a rien sélectionné. Je ne sais pas si j'ai fait quelque chose de mal, mais la modification du nom de l'ID corrige le problème. J'ai simplifié l'exemple, j'espère que c'est clair, sinon s'il vous plaît faites le moi savoir.DropDownList paramètre élément sélectionné dans asp.net MVC

Voici mon avis où l'ID déclaré est le même nom que ma liste dans le modèle:

<table border="0" cellpadding="0" cellspacing="0"> 
    <tr> 
     <td> 
     <%= Html.DropDownList("IsMultipleServicers", Model.IsMultipleServicers) %> 
     </td> 
    </tr> 
</table> 

Et le rendu Html

<table border="0" cellpadding="0" cellspacing="0"> 
     <tr> 
     <td> 
      <select id="IsMultipleServicers" name="IsMultipleServicers"> 
       <option value="false">No</option> 
       <option value="true">Yes</option> 
      </select> 
     </td> 
     </tr> 
</table> 

permet maintenant faire petite monnaie. Je vais changer l'identifiant déclaré pour être quelque chose de différent.

Voici mon avis:

<table border="0" cellpadding="0" cellspacing="0"> 
    <tr> 
     <td> 
      <%= Html.DropDownList("MultipleServicers", Model.IsMultipleServicers) %> 
     </td> 
    </tr> 
</table> 

Et maintenant le code html rendu:

<table border="0" cellpadding="0" cellspacing="0"> 
    <tr> 
     <td> 
     <select id="IsMultipleServicers" name="IsMultipleServicers"> 
      <option value="false">No</option> 
      <option selected="selected" value="true">Yes</option> 
     </select> 
     </td> 
    </tr> 
</table> 

Notez que maintenant je reçois une option choisie qui serait le deuxième élément de la liste.

Voici mon ViewModel juste pour lier le tout:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 

namespace MVCProject.Models.ViewModels.Service 
{ 
    public class ServiceViewModel : ViewModel 
    { 
     public List<SelectListItem> IsMultipleServicers { get; set; } 
    } 
} 

Voici mon action:

[AcceptVerbs(HttpVerbs.Get)] 
public virtual ActionResult Service() 
{ 
    return View(new ServiceViewModel() 
    { 
     IsMultipleServicers = BuildBooleanSelectList(true) 
    }; 
} 

private List<SelectListItem> BuildBooleanSelectList(bool isTrue) 
{ 
    List<SelectListItem> list = new List<SelectListItem>(); 

    if (isTrue) 
    { 
     list.Add(new SelectListItem() { Selected = false, Text = "No", Value = "false" }); 
     list.Add(new SelectListItem() { Selected = true, Text = "Yes", Value = "true" }); 
    } 
    else 
    { 
     list.Add(new SelectListItem() { Selected = true, Text = "No", Value = "false" }); 
     list.Add(new SelectListItem() { Selected = false, Text = "Yes", Value = "true" }); 
    } 
return list; 
    } 

Répondre

43

Je pense que le problème est une confusion en ce qui concerne les DropDownList surcharges:

  1. Html.DropDownList(string name) recherche une propriété de modèle de vue de name et de type IEnumerable<SelectListItem>. Il utilisera l'élément sélectionné (SelectListItem.Selected == true) dans la liste, sauf s'il existe une valeur de formulaire de même nom.

  2. Html.DropDownList(string name, IEnumerable<SelectListItem> selectList) utilise les articles de selectList, mais pas leurs valeurs sélectionnées. Le fichier sélectionné est trouvé en résolvant name dans le modèle de vue (ou en publiant des données) et en le comparant au SelectListItem.Value. Même si la valeur ne peut pas être trouvée (ou est nulle), elle n'utilisera toujours pas la valeur sélectionnée dans la liste de SelectListItems.

Votre code utilise la deuxième surcharge, mais spécifie une propriété « valeur » qui n'existe pas (« MultipleServicers »).

Pour résoudre votre problème, utilisez la première surcharge:

<%= Html.DropDownList("IsMultipleServicers") %> 

Ou, ajoutez une propriété string MultipleServicers à votre modèle de vue et le remplir dans votre contrôleur. Je recommande cette solution car il contourne plusieurs problèmes avec l'affichage initial, l'affichage de poste et la cartographie des données post à un modèle vue/après:

public class ServiceViewModel : ViewModel 
{ 
    public string MultipleServicers { get; set; } 
    public List<SelectListItem> IsMultipleServicers { get; set; } 
} 

Alors pour votre HTML:

<%= Html.DropDownList(Model.MultipleServicers, Model.IsMultipleServicers) %> 

Cette technique mappe également dans MVC2:

<%= Html.DropDownListFor(x => x.MultipleServicers, Model.IsMultipleServicers) %> 
+0

J'aimerais que ce soit plus évident ... Mais c'est logique maintenant. Merci – ppumkin

+0

je vous recommande tout celui-ci: http://www.c-sharpcorner.com/UploadFile/4d9083/creating-simple-cascading-dropdownlist-in-mvc-4-using-razor/ – Umitk

2

L'assistant DropDownList extrait la valeur par défaut du modèle. Dans le premier cas, la valeur dans le modèle correspondant au nom est une SelectList - cela ne correspond à aucun des éléments de la liste, c'est la liste, donc aucune valeur n'est choisie. Dans le deuxième exemple, votre modèle n'inclut pas une propriété portant ce nom, de sorte que la valeur du modèle ne peut pas être utilisée et qu'elle est par défaut l'état indiqué dans la liste SelectList elle-même. Généralement, j'aurai une propriété sur le modèle pour la valeur sélectionnée - ceci devient la valeur par défaut - et une autre propriété représentant les valeurs potentielles pour la liste.

+0

Bonne explication de ce qui est événement! Réglé sur votre pratique par défaut moi-même - semble être le meilleur moyen de rendre les choses explicites, et simplifie la génération des valeurs SelectListItem. –

9

J'ai rencontré ce même problème en utilisant la surcharge Html.DropDownList (nom de chaîne, IEnumerable selectList). Il semble que mon modèle possède une propriété du même nom que le nom de la liste déroulante. Dans ce cas, MVC a favorisé la valeur de propriété de mon modèle sur la propriété Selected de chaque entrée dans IEnumerable.

La solution consistait à utiliser un nom pour la liste déroulante qui ne correspond pas à un nom de propriété. Une autre solution consisterait à écrire ma propre méthode d'extension qui ignore le modèle et l'état d'affichage et, à la place, honore toujours la propriété sélectionnée.

+1

J'ai dû utiliser cette approche avant pour des solutions rapides, mais je pense qu'il est bon de revenir en arrière et de refactoriser vos modèles de vue pour mieux utiliser le Html.DropDownList comme il était destiné à être utilisé (Aussi déroutant que possible) –

Questions connexes