web-dev-qa-db-fra.com

Impossible de convertir le type 'System.Collections.Generic.List <string>' en 'System.Web.Mvc.SelectList'

J'ai la méthode Action suivante, qui ont un viewBag avec une liste de chaînes: -

public ActionResult Login(string returnUrl)
        {
            List<string> domains = new List<string>();
    domains.Add("DomainA");

            ViewBag.ReturnUrl = returnUrl;
            ViewBag.Domains = domains;
            return View();
        }

et sur la vue, j'essaie de construire une liste déroulante qui montre les chaînes de viewBag comme suit: -

@Html.DropDownList("domains",(SelectList)ViewBag.domains )

Mais j'ai eu l'erreur suivante: -

Impossible de convertir le type 'System.Collections.Generic.List' en 'System.Web.Mvc.SelectList'

Alors quelqu'un peut-il dire pourquoi je ne peux pas remplir ma liste déroulante d'une liste de piqûres?

14
john Gu

Parce que DropDownList ne accepte pas une liste de chaînes. Il accepte IEnumerable<SelectListItem>. C'est votre responsabilité de convertir votre liste de chaînes en cela. C'est assez facile cependant:

domains.Select(m => new SelectListItem { Text = m, Value = m })

Ensuite, vous pouvez nourrir cela à DropDownList:

@Html.DropDownList("domains", ((List<string>)ViewBag.domains).Select(m => new SelectListItem { Text = m, Value = m }))
27
Chris Pratt

ViewBag n'est pas fortement typé. Vous pouvez utiliser les classes ViewModel pour transmettre des instances à une vue afin que cette vue puisse utiliser plusieurs sources de données.

    public ActionResult Login(string returnUrl)
    {
        List<string> domains = new List<string>();
        domains.Add("DomainA");

        ViewModel model=new ViewModel();
        model.ReturnUrl = returnUrl;
        model.Domains =new SelectList(domains);
        return View(model);
    }

    Public Class ViewModel()
    {
        property Url ReturnUrl{get;set;}
        property SelectList Domains{get;set;}
    }
4
Thanigainathan

Pour compléter la réponse de Chris Pratt, voici un exemple de code permettant de créer la liste déroulante:

@Html.DropDownList("domains", new SelectList(((List<string>)ViewBag.domains).Select(d => new SelectListItem { Text = d, Value = d }), "Value", "Text"))

Ce qui produira le balisage suivant:

<select id="domains" name="domains">
    <option value="item 1">item 1</option>
    <option value="item 2">item 2</option>
    <option value="item 3">item 3</option>
</select>
3
dom
@Html.DropDownListFor(
     m => m.Country, 
          new SelectList(_CountryList, "CountryID", "Title"),
          new { @class = "form-control" }
)
0
user6683041

Vous devez vraiment avoir une "clé", ou un index, pour chaque valeur, car vous devez convertir chaque nom en un IEnumerable<SelectListItem>, ce qui nécessite une valeur d'ID et une chaîne de texte à afficher. Vous pouvez le faire de deux manières:

Utilise un dictionnaire

Faire un Dictionary<int, string>:

Dictionary<int, string> domainDict = new Dictionary<int, string>();

et chaque fois que vous ajoutez un domaine, vous ajoutez un numéro:

domainDict.Add(1, "DomainA");

Si vous avez une liste source pour cette information avec plusieurs domaines, vous pouvez créer une variable foreach sur cette liste et utiliser une variable d'indexeur similaire à celle que je présente, ci-dessous, au lieu d'ajouter manuellement les éléments.

Vous aurez besoin d'un modèle. Créez une classe appelée DomainViewModel.cs et ajoutez ceci à l'intérieur:

public class DomainViewModel()
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Ensuite, parcourez votre dictionnaire pour ajouter les éléments à une DomainViewModel, puis ajoutez chacun de ces éléments à un List<DomainViewModel>, similaire à ce que j'ai ci-dessous dans la section suivante, sauf que cela ressemblerait à ceci:

List<DomainViewModel> lstDomainModel = new List<DomainViewModel>();

foreach(KeyValuePair<int, string> kvp in domainDict)
{
    DomainViewModel d = new DomainViewModel();
    d.Id = kvp.Key;  // number 
    d.Name = kvp.Value;  // domain name
    lstDomainModel.Add(d);
}

(Passer à Finition , ci-dessous)

Liste des itérations avec indexeur de boucle

Si vous ne souhaitez pas utiliser un Dictionary<>, vous pouvez simplement ajouter l'index à la volée en itérant le List<string> et en le mettant directement dans un List<DomainViewModel>. Voici comment vous feriez cela:

1) Assurez-vous d'avoir créé la classe DomainViewModel.cs ci-dessus.

2) Modifiez votre fonction de contrôleur pour créer votre List<string>, puis parcourez-la pour l'ajouter par fragments de DomainViewModel à un nouveau List<DomainViewModel> à l'aide d'une variable d'indexation (idx):

List<string> domains = new List<string>();
domains.Add("DomainA");  // etc.

List<DomainViewModel> lstDomainModel = new List<lstDomainModel>();
int idx = 0;

// Add your List<string> to your List<DomainViewModel>
foreach (string s in domainList)
{
    DomainViewModel domainModel = new DomainViewModel();
    domainModel.Id = idx;
    domainModel.Name = s;
    lstDomainModel.Add(domainModel);
    idx++;
}

Finir

En utilisant l'une ou l'autre méthode, une fois que vous l'avez dans un List<DomainViewModel>, vous pouvez faire:

IEnumerable<SimpleListItem> domainList = 
    lstDomainModel.Select(d => new SelectListItem { 
            Text = d.Name, 
            Value = d.Id.ToString() 
        }
    );
ViewBag.Domains = domainList;

Et montrez-le dans votre vue comme ceci:

@Html.DropDownList("Domains", (IEnumerable<SelectListItem>)ViewBag.Domains)
0
vapcguy