104 votes

ASP.NET MVC Html.DropDownList ValeurSélectionnée

J'ai essayé ceci dans RC1 puis mis à jour vers RC2 mais cela n'a pas résolu le problème.

// dans mon contrôleur
ViewData["UserId"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // ceci a une valeur

résultat : la propriété SelectedValue est définie sur l'objet

// dans ma vue
<%=Html.DropDownList("UserId", (SelectList)ViewData["UserId"])%>

résultat : toutes les options attendues sont rendues au client, mais l'attribut sélectionné n'est pas défini. L'élément dans SelectedValue existe dans la liste, mais le premier élément de la liste est toujours défini par défaut comme sélectionné.

Comment devrais-je faire cela?

Mise à jour Grâce à la réponse de John Feminella j'ai découvert quelle était la cause du problème. "UserId" est une propriété dans le modèle auquel ma vue est fortement typée. Quand Html.DropDownList("UserId" est changé à n'importe quel autre nom que "UserId", la valeur sélectionnée est rendue correctement.

Cela a pour conséquence que la valeur n'est pas liée au modèle.

0 votes

Etes-vous certain que la valeur est dans la liste?

0 votes

Le problème existe toujours dans la version 1 de ASP.NET MVC

0 votes

Quel est selectedUserId!?

69voto

Sanchitos Points 2263

C'est ainsi que j'ai résolu ce problème:

J'avais ce qui suit:

Contrôleur:

ViewData["DealerTypes"] = Helper.SetSelectedValue(listOfValues, selectedValue) ;

Vue:

<%=Html.DropDownList("DealerTypes", ViewData["DealerTypes"] as SelectList)%>

Modifié par ce qui suit:

Vue

<%=Html.DropDownList("DealerTypesDD", ViewData["DealerTypes"] as SelectList)%>

Il semble que le DropDown ne doit pas avoir le même nom que le nom ViewData :S étrange mais ça a fonctionné.

21 votes

+1 pour "la liste déroulante ne doit pas avoir le même nom que le nom ViewData" Un grand merci

0 votes

Merci!!! Vous venez de résoudre mon problème après de nombreuses heures à me demander pourquoi cela ne fonctionnait pas :)

1 votes

Cela fonctionne pour la valeur sélectionnée, mais un problème survient lorsque vous essayez de mettre à jour "DealerTypes" dans la base de données car le DropDownList est maintenant lié à "DealerTypesDD" qui n'existe pas dans le modèle. Une solution de contournement consiste à ajouter un champ masqué et des attributs HTML au DropDownList : <%= Html.DropDownList("DealerTypesDD", ViewData["DealerTypes"] as SelectList, new { @onchange = "DealerTypes.value = this.value"})%>

51voto

John Feminella Points 116878

Essayer ceci:

public class Person {
    public int Id { get; set; }
    public string Name { get; set; }
}

Et ensuite:

var list = new[] {   
    new Person { Id = 1, Name = "Nom1" }, 
    new Person { Id = 2, Name = "Nom2" }, 
    new Person { Id = 3, Name = "Nom3" } 
};

var selectList = new SelectList(list, "Id", "Name", 2);
ViewData["People"] = selectList;

Html.DropDownList("PeopleClass", (SelectList)ViewData["People"])

Avec MVC RC2, j'obtiens:

    Nom1
    Nom2
    Nom3

0 votes

Cela a été utile pour identifier la cause. J'ai mis à jour ma question pour refléter les ajouts.

0 votes

Est-ce que le premier est dans le modèle? le deuxième dans le contrôleur? et le troisième dans la vue c'est clair, mais les 2 premiers...???

0 votes

Bonne réponse, mais n'est-il pas préférable d'utiliser un ViewModel ?

5voto

Rui Points 2159

Vous pouvez toujours nommer le DropDown comme "UserId" et avoir une liaison de modèle qui fonctionne correctement pour vous.

La seule exigence pour que cela fonctionne est que la clé ViewData qui contient le SelectList n'ait pas le même nom que la propriété du modèle à laquelle vous souhaitez lier. Dans votre cas spécifique, ce serait:

// dans mon contrôleur
ViewData["Users"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // cela a une valeur

// dans ma vue
<%=Html.DropDownList("UserId", (SelectList)ViewData["Users"])%>

Cela produira un élément select nommé UserId, qui a le même nom que la propriété UserId dans votre modèle et donc le model binder le définira avec la valeur sélectionnée dans l'élément select html généré par l'assistant Html.DropDownList.

Je ne suis pas sûr pourquoi ce constructeur particulier de Html.DropDownList ne sélectionnera pas la valeur spécifiée dans le SelectList lorsque vous mettez la liste déroulante dans la ViewData avec une clé égale au nom de la propriété. Je soupçonne que cela a quelque chose à voir avec la façon dont l'assistant DropDownList est utilisé dans d'autres scénarios, où la convention est que vous avez en effet un SelectList dans la ViewData avec le même nom que la propriété dans votre modèle. Cela fonctionnera correctement:

// dans mon contrôleur
ViewData["UserId"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // cela a une valeur

// dans ma vue
<%=Html.DropDownList("UserId")%>

0 votes

Merci beaucoup mec, surtout toutes les réponses, celle-ci a fonctionné pour moi, je ne sais pas pourquoi mais ça a marché

0 votes

Enfin ! Après des heures d'essais, j'ai enfin trouvé votre "seule exigence". Cela l'a fait.

3voto

wayne.blackmon Points 311

Le code dans le précédent post sur MVC 3 ne fonctionne pas mais c'est un bon début. Je vais le corriger. J'ai testé ce code et il fonctionne en MVC 3 Razor C#. Ce code utilise le pattern ViewModel pour peupler une propriété qui retourne une List<SelectListItem>.

La classe Modèle

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

La classe ViewModel

using System.Web.Mvc;

public class ProductListviewModel
{
    public List<SelectListItem> Products { get; set; }
}

La méthode du Contrôleur

public ViewResult List()
{
    var productList = new List<SelectListItem>();

    foreach (Product p in Products)
    {
        productList.Add(new SelectListItem
        {
            Value = p.ProductId.ToString(),
            Text = "Product: " + p.Name + " " + p.Price.ToString(),
            // Pour définir l'élément sélectionné, utilisez le code suivant
            // Remarque : vous ne devriez pas définir chaque élément comme sélectionné
            Selected = true
        });
    }

    ProductListViewModel productListVM = new ProductListViewModel();

    productListVM.Products = productList;

    return View(productListVM);
}

La vue

@model MvcApp.ViewModels.ProductListViewModel

@using (Html.BeginForm())
{
    @Html.DropDownList("Products", Model.Products)
}

La sortie HTML sera quelque chose comme

    Produit: Widget 10.00
    Produit: Gadget 5.95

en fonction de la façon dont vous formatez la sortie. J'espère que cela vous aidera. Le code fonctionne effectivement.

1 votes

Cela ne définit pas l'option sélectionnée.

0 votes

Pour définir l'élément sélectionné en utilisant SelectListItem, définissez la propriété Selected sur true.

1voto

Paul Hatcher Points 193

Cela semble être un bug dans la classe SelectExtensions car elle ne vérifiera que le ViewData plutôt que le modèle pour l'élément sélectionné. La solution consiste donc à copier l'élément sélectionné du modèle dans la collection ViewData sous le nom de la propriété.

Ceci est tiré de la réponse que j'ai donnée sur les forums MVC, j'ai également une réponse plus complète dans un article de blog qui utilise l'attribut DropDownList de Kazi...

Étant donné un modèle

public class ArticleType
{
   public Guid Id { get; set; }
   public string Description { get; set; }
}

public class Article
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ArticleType { get; set; }
}

et un modèle de vue de base de

public class ArticleModel
{
     public Guid Id { get; set; }
     public string Name { get; set; }

     [UIHint("DropDownList")]
     public Guid ArticleType { get; set; }
}

Ensuite, nous écrivons un modèle d'éditeur de DropDownList comme suit..

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

    IEnumerable<SelectListItem> GetSelectList()
    {
        var metaData = ViewData.ModelMetadata;
        if (metaData == null)
        {
            return null;
        }

        var selected = Model is SelectListItem ? ((SelectListItem) Model).Value : Model.ToString();
        ViewData[metaData.PropertyName] = selected;

        var key = metaData.PropertyName + "List";
        return (IEnumerable<SelectListItem>)ViewData[key];
    }

<%= Html.DropDownList(null, GetSelectList()) %>

Cela fonctionnera également si vous changez ArticleType dans le modèle de vue en SelectListItem, bien que vous deviez implémenter un convertisseur de type comme dans le blog de Kazi et l'enregistrer pour forcer le binder à traiter ceci comme un type simple.

Dans votre contrôleur nous avons alors...

public ArticleController 
{
     ...
     public ActionResult Edit(int id)
     {
          var entity = repository.FindOne

0 votes

Merci pour la réponse, je vais devoir vérifier cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X