So erhalten Sie die Werte einer Aufzählung in eine SelectList

71

Stellen Sie sich vor, ich habe eine Aufzählung wie diese (nur als Beispiel):

public enum Direction{
    Horizontal = 0,
    Vertical = 1,
    Diagonal = 2
}

Wie kann ich eine Routine schreiben, um diese Werte in eine System.Web.Mvc.SelectList zu übernehmen, da sich der Inhalt der Aufzählung in Zukunft ändern kann? Ich möchte jeden Aufzählungsnamen als Optionstext und seinen Wert als Wertetext wie folgt erhalten:

<select>
    <option value="0">Horizontal</option>
    <option value="1">Vertical</option>
    <option value="2">Diagonal</option>
</select>

Dies ist das Beste, was ich bisher finden kann:

 public static SelectList GetDirectionSelectList()
 {
    Array values = Enum.GetValues(typeof(Direction));
    List<ListItem> items = new List<ListItem>(values.Length);

    foreach (var i in values)
    {
        items.Add(new ListItem
        {
            Text = Enum.GetName(typeof(Direction), i),
            Value = i.ToString()
        });
    }

    return new SelectList(items);
 }

Dadurch wird der Optionstext jedoch immer als "System.Web.Mvc.ListItem" dargestellt. Das Debuggen zeigt mir auch, dass Enum.GetValues ​​() wie erwartet 'Horizontal, Vertikal' usw. anstelle von 0, 1 zurückgibt, was mich fragen lässt, was der Unterschied zwischen Enum.GetName () und Enum ist. Wert erhalten().

Lee D.
quelle
1
Dies ist ein großes Duplikat von stackoverflow.com/questions/1102022/… und vielen, vielen anderen.
John Saunders

Antworten:

28

Um den Wert einer Aufzählung zu erhalten, müssen Sie die Aufzählung in den zugrunde liegenden Typ umwandeln:

Value = ((int)i).ToString();
Andrew Hare
quelle
Vielen Dank! Ich dachte darüber nach, dachte aber, dass es einen Weg geben könnte, es ohne Casting zu tun.
Lee D
87

Es ist schon eine Weile her, dass ich das tun musste, aber ich denke, das sollte funktionieren.

var directions = from Direction d in Enum.GetValues(typeof(Direction))
           select new { ID = (int)d, Name = d.ToString() };
return new SelectList(directions , "ID", "Name", someSelectedValue);
Brandon
quelle
5
Funktioniert fast, braucht nur eine kleine Änderung! Ihr Code setzt den Wert auf Text, wenn das OP wollte, dass es eine Ganzzahl ist. Einfache Lösung. Wechseln Sie ID = dzu ID = (int)d. Danke, dass du das gepostet hast, ich hätte nie daran gedacht!
Chris
Gute Antwort, obwohl ich festgestellt habe, dass der Wert die Textdarstellung der Aufzählung und nicht die Ganzzahl sein muss, um das Dropdown-Menü vorab auszufüllen.
Luke Alderton
40

Hierfür gibt es in ASP.NET MVC 5.1 eine neue Funktion.

http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum

@Html.EnumDropDownListFor(model => model.Direction)
Fred
quelle
Gibt es eine taghelperVersion davon?
Serj Sagan
3
@ SerjSagan, ja. <select asp-items="Html.GetEnumSelectList<Direction>()"></select>.
Fred
Wie erhalten Sie den ausgewählten Wert in der Steuerung daraus?
Transformator
33

Das habe ich gerade gemacht und persönlich finde ich es sexy:

 public static IEnumerable<SelectListItem> GetEnumSelectList<T>()
        {
            return (Enum.GetValues(typeof(T)).Cast<T>().Select(
                enu => new SelectListItem() { Text = enu.ToString(), Value = enu.ToString() })).ToList();
        }

Ich werde irgendwann ein paar Übersetzungsarbeiten machen, damit Value = enu.ToString () irgendwo etwas aufruft.

Dan
quelle
1
Ich habe ein Problem mit diesem Code. Der "Wert" der SelectList entspricht dem "Text". Bei Verwendung von Enums mit EntityFramework muss der in der Datenbank gespeicherte Wert int sein.
Northstrider
Ok, dann mach das gut: Value = (int) enu
Dan
Der Grund, warum (int) enu im obigen Beispiel nicht funktioniert, ist, dass die Value-Eigenschaft von SelectListItem eine Zeichenfolge und keine Ganzzahl ist. ((int) enu) .ToString () funktioniert.
Teppic
Nein, wird es nicht. Im obigen Beispiel kennt es zur Kompilierungszeit den Typ von nicht T. Als solches kann man das nicht intmögen.
Ajbeaven
Ab C # 7.3 können Sie jetzt 'where T: System.Enum' hinzufügen.
Johan Maes
24

Ich wollte etwas tun, das Danns Lösung sehr ähnlich ist, aber ich brauchte den Wert als int und den Text als Zeichenfolgendarstellung der Aufzählung. Folgendes habe ich mir ausgedacht:

public static IEnumerable<SelectListItem> GetEnumSelectList<T>()
    {
        return (Enum.GetValues(typeof(T)).Cast<int>().Select(e => new SelectListItem() { Text = Enum.GetName(typeof(T), e), Value = e.ToString() })).ToList();
    }
J. Noel.K
quelle
1
Dies ist bei weitem die bessere Antwort. Der Wert musste eine int-Darstellung von enum sein.
Fahad Abid Janjua
12

In ASP.NET Core MVC erfolgt dies mit Tag-Helfern .

<select asp-items="Html.GetEnumSelectList<Direction>()"></select>
Fred
quelle
Was ist mit dem Einstellen des ausgewählten Lasts?
JordanGW
Dann müssen Sie das asp-forAttribut angeben .
Fred
4

Vielleicht keine genaue Antwort auf die Frage, aber in CRUD-Szenarien implementiere ich normalerweise so etwas:

private void PopulateViewdata4Selectlists(ImportJob job)
{
   ViewData["Fetcher"] = from ImportFetcher d in Enum.GetValues(typeof(ImportFetcher))
                              select new SelectListItem
                              {
                                  Value = ((int)d).ToString(),
                                  Text = d.ToString(),
                                  Selected = job.Fetcher == d
                              };
}

PopulateViewdata4Selectlists wird vor Ansicht ("Erstellen") und Ansicht ("Bearbeiten") aufgerufen, dann und in der Ansicht:

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

und das ist alles..

Carl Hörberg
quelle
4

Oder:

foreach (string item in Enum.GetNames(typeof(MyEnum)))
{
    myDropDownList.Items.Add(new ListItem(item, ((int)((MyEnum)Enum.Parse(typeof(MyEnum), item))).ToString()));
}
zkarolyi
quelle
4
return
            Enum
            .GetNames(typeof(ReceptionNumberType))
            .Where(i => (ReceptionNumberType)(Enum.Parse(typeof(ReceptionNumberType), i.ToString())) < ReceptionNumberType.MCI)
            .Select(i => new
            {
                description = i,
                value = (Enum.Parse(typeof(ReceptionNumberType), i.ToString()))
            });
Hamid
quelle
3
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum)) select new { ID = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };
        //var values = from TEnum e in Enum.GetValues(typeof(TEnum)) select new { ID = e, Name = e.ToString() };

        return new SelectList(values, "ID", "Name", enumObj);
    }
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj, string selectedValue) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum)) select new { ID = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };
        //var values = from TEnum e in Enum.GetValues(typeof(TEnum)) select new { ID = e, Name = e.ToString() };
        if (string.IsNullOrWhiteSpace(selectedValue))
        {
            return new SelectList(values, "ID", "Name", enumObj);
        }
        else
        {
            return new SelectList(values, "ID", "Name", selectedValue);
        }
    }
Joao Leme
quelle
2

Ich habe aus verschiedenen Gründen mehr Klassen und Methoden:

Aufzählung zur Sammlung von Gegenständen

public static class EnumHelper
{
    public static List<ItemDto> EnumToCollection<T>()
    {
        return (Enum.GetValues(typeof(T)).Cast<int>().Select(
            e => new ItemViewModel
                     {
                         IntKey = e,
                         Value = Enum.GetName(typeof(T), e)
                     })).ToList();
    }
}

Auswahlliste in Controller erstellen

int selectedValue = 1; // resolved from anywhere
ViewBag.Currency = new SelectList(EnumHelper.EnumToCollection<Currency>(), "Key", "Value", selectedValue);

MyView.cshtml

@Html.DropDownListFor(x => x.Currency, null, htmlAttributes: new { @class = "form-control" })
Miroslav Holec
quelle
2

Ich hatte viele Enum-Auswahllisten und stellte nach langem Jagen und Sieben fest, dass es für mich am besten war, einen generischen Helfer zu erstellen. Es gibt den Index oder Deskriptor als Selectlist-Wert und die Beschreibung als Selectlist-Text zurück:

Aufzählung:

public enum Your_Enum
{
    [Description("Description 1")]
    item_one,
    [Description("Description 2")]
    item_two
}

Helfer:

public static class Selectlists
{
    public static SelectList EnumSelectlist<TEnum>(bool indexed = false) where TEnum : struct
    {
        return new SelectList(Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Select(item => new SelectListItem
        {
            Text = GetEnumDescription(item as Enum),
            Value = indexed ? Convert.ToInt32(item).ToString() : item.ToString()
        }).ToList(), "Value", "Text");
    }

    // NOTE: returns Descriptor if there is no Description
    private static string GetEnumDescription(Enum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attributes != null && attributes.Length > 0)
            return attributes[0].Description;
        else
            return value.ToString();
    }
}

Verwendung: Setzen Sie den Parameter für Indizes als Wert auf 'true':

var descriptorsAsValue = Selectlists.EnumSelectlist<Your_Enum>();
var indicesAsValue = Selectlists.EnumSelectlist<Your_Enum>(true);
RickL
quelle