Comment puis-je avoir ça? ASP.NET MVC SelectList to work?

je crée une selectList dans mon contrôleur, pour l'afficher dans la vue.

j'essaie de le créer à la volée .. pareil...

myViewData.PageOptionsDropDown = 
   new SelectList(new [] {"10", "15", "25", "50", "100", "1000"}, "15");

il compile, mais la sortie est mauvaise...

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
    <option>10</option>
    <option>15</option>
    <option>25</option>
    <option>50</option>
    <option>100</option>
    <option>1000</option>
</select>

Remarquez comment aucun élément n'est sélectionné?

Comment puis-je réparer ça??

122
demandé sur C. Ross 2009-04-23 18:23:20

23 réponses

C'est comment je le fais

IList<Customer> customers = repository.GetAll<Customer>();
IEnumerable<SelectListItem> selectList = 
    from c in customers
    select new SelectListItem
    {
        Selected = (c.CustomerID == invoice.CustomerID),
        Text = c.Name,
        Value = c.CustomerID.ToString()
    };

à première vue, Je ne suis pas sûr de savoir ce que vous recherchez...

124
répondu mhenrixon 2009-04-23 14:33:06

j'utilise une méthode d'extension:

utilisation

var departmentItems = departments.ToSelectList(d => d.Code + 
                                               " - " + d.Description,
                                               d => d.Id.ToString(),
                                               " - ");

var functionItems = customerFunctions.ToSelectList(f => f.Description, 
                                                   f => f.Id.ToString(), 
                                                   " - ");

avec

public static class MCVExtentions
{
    public static List<SelectListItem> ToSelectList<T>(
        this IEnumerable<T> enumerable, 
        Func<T, string> text, 
        Func<T, string> value, 
        string defaultOption)
    {
        var items = enumerable.Select(f => new SelectListItem()
                                     {
                                         Text = text(f), 
                                         Value = value(f) 
                                     }).ToList();
        items.Insert(0, new SelectListItem()
                    {
                        Text = defaultOption, 
                        Value = "-1" 
                    });
        return items;
    }
}
68
répondu Thomas Stock 2015-05-28 19:50:41

utilisant le constructeur qui accepte items, dataValueField, dataTextField, selectedValue comme paramètres:

ViewData["myList"] = 
                new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }
                .Select(x => new {value = x, text = x}), 
                "value", "text", "15");

Alors à votre avis :

<%=Html.DropDownList("myList") %>
47
répondu Çağdaş Tekin 2009-07-21 12:52:39

construisant la réponse de Thomas Stock, j'ai créé ces méthodes surchargées ToSelectList :

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

public static partial class Helpers
{
    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, bool selectAll = false)
    {
        return enumerable.ToSelectList(value, value, selectAll);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, object selectedValue)
    {
        return enumerable.ToSelectList(value, value, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, IEnumerable<object> selectedValues)
    {
        return enumerable.ToSelectList(value, value, selectedValues);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, bool selectAll = false)
    {
        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = selectAll
            };
        }
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, object selectedValue)
    {
        return enumerable.ToSelectList(value, text, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, IEnumerable<object> selectedValues)
    {
        var sel = selectedValues != null
            ? selectedValues.Where(x => x != null).ToList().ConvertAll<string>(x => x.ToString())
            : new List<string>();

        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = sel.Contains(value(f).ToString())
            };
        }
    }
}

Dans votre contrôleur, vous pouvez faire ce qui suit:

var pageOptions = new[] { "10", "15", "25", "50", "100", "1000" };
ViewBag.PageOptions = pageOptions.ToSelectList(o => o, "15" /*selectedValue*/);

et enfin à votre avis, mettre:

@Html.DropDownList("PageOptionsDropDown", ViewBag.PageOptions as IEnumerable<SelectListItem>, "(Select one)")

il en résultera la sortie désirée--bien sûr, vous pouvez laisser de côté l'option "(Select one)" ci-dessus si vous ne voulez pas le premier article vide:

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option value="">(Select one)</option>
<option value="10">10</option>
<option selected="selected" value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="1000">1000</option>
</select>

mise à jour: une liste de codes révisée peut être trouvé ici avec des commentaires XML.

18
répondu JustinStolle 2014-09-20 21:50:44

le problème est, SelectList fonctionne comme prévu. Le bug est dans le design. Vous pouvez définir la propriété sélectionnée dans SelectedItem, mais cela sera complètement ignoré, si vous parcourez la liste avec le GetEnumerator() (ou si Mvc le fait pour vous). Mvc va créer de nouveaux SelectListItems à la place.

vous devez utiliser le SelectList ctor avec le SelectListItem[], le Text-Name, Le Value-Name et la SelectedValue. Être conscient de passer comme SelectedValue la valeur de SelectListItem, que vous voulez être sélectionné, pas le SelectListItem lui-même! Exemple:

SelectList sl = new SelectList( new[]{
  new SelectListItem{ Text="one", Value="1"},
  new SelectListItem{ Text="two", Value="2"},
  new SelectListItem{ Text="three", Value="3"}
}, "Text", "Value", "2" );

(pas testé, mais j'ai eu le même problème)

alors la 2e option obtiendra l'attribut selected=" selected". Qui ressemble à un bon vieux jeux de données ;-)

13
répondu Gone Coding 2013-07-11 14:30:48

C'est une option:

myViewData.PageOptionsDropDown = new[] 
{
 new SelectListItem { Text = "10", Value = "10" },
 new SelectListItem { Text = "15", Value = "15", Selected = true }
 new SelectListItem { Text = "25", Value = "25" },
 new SelectListItem { Text = "50", Value = "50" },
 new SelectListItem { Text = "100", Value = "100" },
 new SelectListItem { Text = "1000", Value = "1000" },
}
11
répondu murki 2009-07-08 18:29:13

si c'est littéralement tout ce que vous voulez faire, alors il suffit de déclarer le tableau comme chaîne de caractères pour corriger le problème de l'élément sélectionné:

myViewData.PageOptionsDropDown = 
   new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");
10
répondu Matt Cotton 2011-01-15 18:02:30

il est très simple d'obtenir SelectList et SelectedValue travaillant ensemble, même si votre propriété n'est pas un objet simple comme un Int, une chaîne ou une Double valeur.

exemple:

en supposant que notre objet de région est quelque chose comme ceci:

public class Region {
     public Guid ID { get; set; }
     public Guid Name { get; set; }
}

et votre modèle de vue est quelque chose comme:

public class ContactViewModel {
     public DateTime Date { get; set; }
     public Region Region { get; set; }
     public List<Region> Regions { get; set; }
}

vous pouvez avoir le code ci-dessous:

@Html.DropDownListFor(x => x.Region, new SelectList(Model.Regions, "ID", "Name")) 

seulement si vous outrepassez la méthode ToString de la région object à quelque chose comme:

public class Region {
     public Guid ID { get; set; }
     public Guid Name { get; set; }

     public override string ToString()
     {
         return ID.ToString();
     }
}

cela ont 100% garantie de travailler.

mais je crois vraiment que la meilleure façon D'obtenir SelectList 100% de travail dans toutes les circonstances est en utilisant la méthode Equal pour tester la valeur des propriétés DropDownList ou ListBox par rapport à chaque élément de la collection d'éléments.

6
répondu ararog 2012-07-28 23:08:30

il semble que si vous avez une vue fortement dactylographiée vous devez changer L'ID du dropdown de sorte qu'il ne soit pas le nom d'une propriété sur la classe héritée. Vous devez ensuite mettre un peu de logique dans votre méthode edit (POST) pour retirer la valeur sélectionnée de la section FORMCollection et la mettre sur votre instance avant de propager vos modifications.

C'est certainement un peu étrange, mais je l'ai essayé et il fonctionne.

donc si votre classe a un champ appelé CountryId dire, et vous êtes l'affichage d'une liste de noms de pays, de faire la liste déroulante avoir un id de CountryName plutôt que CountryId, puis dans le post, vous pouvez faire quelque chose avec de la Collection["CountryName"].

4
répondu 2009-07-28 11:23:43

j'ai eu exactement le même problème. La solution est simple. Il suffit de changer le paramètre "name" passé au helper DropDownList en quelque chose qui ne correspond à aucune des propriétés existant dans votre ViewModel. lire la suite ici: http://www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

je cite le Dan Watson:

dans MVC si la vue est fortement typée le selectlist de l'option sélectionnée sera remplacée et l'option sélectionnée propriété définie dans le constructeur n'atteindra jamais la vue et la première option dans la liste déroulante sera sélectionné (pourquoi encore un peu de mystère).

santé!

4
répondu cleftheris 2011-09-05 18:01:45

toutes ces réponses semblent excellentes, mais il semble que le contrôleur prépare des données pour une vue dans un format structuré bien connu vs. laisser la vue itérer simplement un IEnumerable<> livré via le modèle et construire une liste de sélection standard puis laisser DefaultModelBinder vous livrer l'élément sélectionné via un paramètre d'action. Oui, non, pourquoi pas? Séparation des préoccupations, Oui? Semble étrange d'avoir le contrôleur pour construire quelque chose si UI et voir spécifique.

2
répondu slimflem 2011-01-26 19:38:10

Simple:

string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
myViewData.PageOptionsDropDown = new SelectList(someName, "15");
2
répondu Munk 2012-12-21 22:02:51

en utilisant votre exemple cela a fonctionné pour moi:

contrôleur:

ViewData["PageOptionsDropDown"] = new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");

:

<%= Html.DropDownList("PageOptionsDropDown")%>
1
répondu Cadoo 2009-06-26 17:26:24

j'ai juste couru comme ça et n'avait pas de problèmes",

public class myViewDataObj
    {
        public SelectList PageOptionsDropDown { get; set; }
    }

public ActionResult About()
        {
            myViewDataObj myViewData = new myViewDataObj();
            myViewData.PageOptionsDropDown =
                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");

            ViewData["myList"] = myViewData.PageOptionsDropDown;
            return View();
        }

et

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

ça a aussi marché si vous faites ça,

public ActionResult About()
        {
            myViewDataObj myViewData = new myViewDataObj();
            myViewData.PageOptionsDropDown =
                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" });

            ViewData["myListValues"] = myViewData.PageOptionsDropDown;
            ViewData["myList"] = "15";
            return View();
        }

et

<%=Html.DropDownList("myList",(IEnumerable<SelectListItem>)ViewData["myListValues"]) %>
1
répondu Tony Borf 2009-07-21 13:42:36
MonthRepository monthRepository = new MonthRepository();
IQueryable<MonthEntity> entities = monthRepository.GetAllMonth();
List<MonthEntity> monthEntities = new List<MonthEntity>();

foreach(var r in entities)
{
    monthEntities.Add(r);
}

ViewData["Month"] = new SelectList(monthEntities, "MonthID", "Month", "Mars");
1
répondu Cactus 2010-03-17 01:24:46

je fais comme ça:

List<SelectListItem> list = new List<SelectListItem>{
new SelectListItem {Selected = true, Text = "Select", Value = "0"},
new SelectListItem {Selected = true, Text = "1", Value = "1"},
new SelectListItem {Selected = true, Text = "2", Value = "2"}
};
return list.ToArray();

Le ToArray() s'occupe des problèmes.

1
répondu femseks 2010-09-30 07:55:25

si vous voulez passer un texte aléatoire à votre liste déroulante, par exemple -- sélectionnez-- vous pouvez facilement faire cela en utilisant ce code:

@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })
1
répondu Münich 2016-01-04 17:50:58

il se peut que vous ayez une ambiguïté dans vos données de vue:

regardez ici

0
répondu KP. 2017-05-23 12:02:59

la valeur sélectionnée dans le modèle prend avantage au lieu de l'élément par défaut. (Je suis d'accord je n'ai pas lu tous les posts)

0
répondu Daniel 2010-03-28 16:33:43

Je ne me souviens pas comment mvc 1 a été configuré, mais il semble qu'il voulait la liste de sélection nommée la même que le champ qu'il appartenait aussi...

ce que j'ai trouvé, comme quelqu'un l'a dit plus haut, c'est que mes listes de sélection ne fonctionnaient pas dans mvc2 lorsque la ViewData qu'elles ont été envoyées sous le même nom que le champ.

par exemple:

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForName"]) %>

fonctionne quand

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForID"]) %>

ne fonctionne pas car le nom de ViewData "ForID" est nommé de la même manière que le champ pour lequel il travaille

0
répondu Mark 2010-09-17 00:12:26

une explication possible est que la valeur selectlist à laquelle vous êtes lié n'est pas une chaîne de caractères.

donc dans cet exemple, le paramètre 'PageOptionsDropDown' est-il une chaîne de caractères dans votre modèle? Parce que si ce n'est pas le cas, la valeur sélectionnée dans la liste ne sera pas affichée.

0
répondu FruitDealer 2010-12-13 03:58:00

si vous regardez dans le code source de MVC 2 au Html.Méthode d'extension DropDownList, elle ne vérifie jamais la propriété SelectList class SelectedValue. Il n'essaiera jamais de rivaliser avec votre modèle.

Tout ce qui précède sont toutes les variations sur un thème, c'est-à-dire comment envoyer un tas de données à la vue pour une liste déroulante et ils sont tous aussi bons les uns que les autres (plus ou moins).

Le problème est dans la vue. Créer votre propre DropDownList méthode d'extension qui respecte la valeur selectvalue que vous définissez, ou itérer cependant à la main. Qui fonctionne le mieux pour vous.

0
répondu Simon Halsey 2011-01-03 15:39:17

si vous avez une collection dans votre modèle et que votre vue est fortement typée, une variante de ceci fonctionnera:

@Html.DropDownListFor(x => x.RegionID, 
    new SelectList(Model.Regions,"RegionID", "RegionName", Model.RegionID))

-ou-

@Html.DropDownList("RegionID", 
    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
0
répondu Mark 2011-09-30 20:43:15