741 Stimmen

Wie erstellen Sie eine Dropdownliste aus einer Aufzählung in ASP.NET MVC?

Ich versuche, die Html.DropDownList Erweiterungsmethode, kann aber nicht herausfinden, wie man sie mit einer Aufzählung verwenden kann.

Nehmen wir an, ich habe eine Aufzählung wie diese:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

Wie erstelle ich eine Auswahlliste mit diesen Werten unter Verwendung der Html.DropDownList Erweiterungsmethode?

Oder ist meine beste Wette, um einfach eine for-Schleife erstellen und die Html-Elemente manuell erstellen?

51voto

Zaid Masud Punkte 12759

Html.DropDownListFor erfordert nur ein IEnumerable, so dass eine Alternative zu Prise Lösung ist wie folgt. Dies ermöglicht es Ihnen, einfach zu schreiben:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

(wobei SelectedItemType ein Feld Ihres Modells vom Typ ItemTypes ist und Ihr Modell nicht leer ist)

Außerdem müssen Sie die Erweiterungsmethode nicht unbedingt generisch gestalten, da Sie enumValue.GetType() statt typeof(T) verwenden können.

EDIT: Ich habe Simons Lösung auch hier integriert und die Erweiterungsmethode ToDescription hinzugefügt.

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

0 Stimmen

Funktioniert bei mir nicht ('System.NullReferenceException: Object reference not set to an instance of an object.')... Mein 'Model' ist null... hat wahrscheinlich etwas mit 'GetNonNullableModelType' zu tun, das Simon eingebunden hat

0 Stimmen

@Cristi, Sie haben Recht, dass diese Lösung nicht für den Fall gedacht ist, dass Ihr Modell null ist. Ich versuche, ein solches Design im Allgemeinen zu vermeiden und initialisiere ein "leeres" Modell, wenn dies der Fall ist.

0 Stimmen

Nun, ich bin neu in asp mvc, aber ich habe ziemlich Erfahrung in .Net. Danke, ich werde mir das ansehen, was Sie vorschlagen. Btw Ihre ToDescription Erweiterung ist weit außerhalb der 'Enum' Bereich. Ich schätze, das gilt auch für das 'Object' selbst. Dies ist, was ich verwendet habe, als ich Simons Code nahm und ihn ein bisschen mehr aufräumte.

35voto

Marty Trenouth Punkte 3642

Also ohne Erweiterungsfunktionen, wenn Sie auf der Suche nach einem einfachen und leicht. Dies ist, was ich tat

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

wobei XXXXX.Sites.YYYY.Models.State eine Aufzählung ist

Wahrscheinlich ist es besser, eine Hilfsfunktion zu verwenden, aber wenn die Zeit knapp ist, wird dies die Aufgabe erfüllen.

0 Stimmen

Nizza dies funktionierte Auffüllen der Dropdown, aber wie Sie den Standard ausgewählten Wert in der Razor-Syntax für Html.DropDownListFor festlegen? Ich möchte eine Tabelle mit Comboboxen von Enums zeigen, und ich muss den ausgewählten Wert auch nach dem, was es vorher war, einstellen.

2 Stimmen

Es sollte möglich sein, einen zweiten Parameter mit dem ausgewählten Wert an die neue Funktion SelectList(IEnumerable,object) zu übergeben. MSDN-Dokumentation: msdn.microsoft.com/de-us/library/dd460123.aspx

25voto

Nathan Taylor Punkte 24098

Wenn Sie die Antworten von Prise und Rune weiter ausführen und das Attribut value Ihrer Auswahllistenelemente dem Integer-Wert des Typs Enumeration und nicht dem String-Wert zuordnen möchten, verwenden Sie den folgenden Code:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if(!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

Anstatt jeden Aufzählungswert als TEnum-Objekt zu behandeln, können wir ihn als Objekt behandeln und ihn dann in eine Ganzzahl umwandeln, um den unboxed-Wert zu erhalten.

Anmerkung: Ich habe auch eine generische Typbeschränkung hinzugefügt, um die Typen, für die diese Erweiterung verfügbar ist, auf structs (den Basistyp von Enum) zu beschränken, und eine Laufzeit-Typüberprüfung, die sicherstellt, dass die übergebene struct tatsächlich eine Enum ist.

Update 23.10.12: Generischer Typ-Parameter für zugrundeliegenden Typ hinzugefügt und Problem der Nichtkompilierung in .NET 4+ behoben.

0 Stimmen

Danke! Das war die Antwort, die ich brauchte. Ich speichere eine Enum Integer-Wert als eine Spalte in der Datenbank und diese Lösung scheint perfekt zu funktionieren.

0 Stimmen

Aber was, wenn Sie ein Zeichen und nicht ein int speichern? was mein Fall ist. offensichtlich könnte ich (int) zu (char) ändern, aber wie über die Herstellung dieser generischen als auch. wie das zu tun?

0 Stimmen

@Stefandvds Das ist eine gute Frage in Bezug auf das Gießen auf den richtigen dargestellten Typ. Basierend auf den Tests, die ich gerade durchgeführt habe, scheint es, dass die einzige Möglichkeit, dies zu erreichen, darin besteht, den tatsächlichen Typ als weiteren Typparameter anzugeben. ToSelectList<TEnum, TEnumValue>(this TEnum enumObj) { ... }

14voto

GoldenAge Punkte 2578

In .NET Core können Sie einfach dies verwenden:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())

2 Stimmen

Oder mit dem Tag-Helfer <select asp-for="Model.Foo" class="form-control" asp-items="@Html.GetEnumSelectList<MyEnum>()"></select> .

0 Stimmen

Yep, ich würde sagen, Tag-Helfer sind sogar besser, da das Format näher am reinen HTML ist ;)

0 Stimmen

Sie können auch Folgendes tun @Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList(typeof(FooEnum)))

12voto

ceedee Punkte 186

Lösung des Problems, die Zahl anstelle des Textes zu erhalten, mit der Erweiterungsmethode von Prise.

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}

0 Stimmen

Das ist genau das, was ich gesucht habe, obwohl es ein bisschen hässlicher ist, als ich dachte, dass es sein müsste. Ich frage mich, warum Visual Studio lässt Sie nicht direkt Cast e à int .

0 Stimmen

Oder Sie könnten einfach Folgendes verwenden ID = Convert.ToInt32(e) .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X