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?

8voto

Mr. Flibble Punkte 25755

Dies sind die Antworten von Rune & Prise, die so geändert wurden, dass sie das Enum verwenden int Wert als die ID.

Beispiel-Enum:

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

Methode der Verlängerung:

    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", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

Beispiel für die Verwendung:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

Denken Sie daran, den Namespace zu importieren, der die Erweiterungsmethode enthält

<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>

Beispiel für generiertes HTML:

<select id="MyEnumList" name="MyEnumList">
    <option value="1">Movie</option>
    <option selected="selected" value="2">Game</option>
    <option value="3">Book </option>
</select>

Beachten Sie, dass das Element, das Sie zum Aufrufen der ToSelectList on ist das ausgewählte Element.

0 Stimmen

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

8voto

user550950 Punkte 51

Dies ist die Version für Razor:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }

@Html.DropDownList("ItemTypeId", itemTypesList)

0 Stimmen

Das funktioniert nur, wenn Ihr Enum aus zusammenhängenden Werten besteht, die mit 0 beginnen. Ein Flags-Enum würde damit nicht funktionieren. Kreative Nutzung der indizierten Select, obwohl.

6voto

NinjaNye Punkte 6788

Nun, ich bin wirklich spät dran, aber ich habe über genau dieses Thema gebloggt, wobei ich eine EnumHelper Klasse, die eine sehr einfache Transformation ermöglicht.

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

In Ihrem Controller:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

In Ihrer Ansicht:

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

Die Hilfsklasse:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
        }

        return value.ToString();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}

6voto

PaulTheCyclist Punkte 1187

Ein ähnlicher Ansatz, der auf Simons Antwort aufbaut, besteht darin, die anzuzeigenden Enum-Werte aus einer Ressourcendatei zu beziehen, anstatt sie in einem Beschreibungsattribut innerhalb des Enums selbst zu speichern. Dies ist hilfreich, wenn Ihre Website in mehr als einer Sprache gerendert werden muss, und wenn Sie eine spezielle Ressourcendatei für Enums haben, könnten Sie einen Schritt weiter gehen und nur Enum-Werte in Ihrem Enum haben und sie von der Erweiterung durch eine Konvention wie [EnumName]_[EnumValue] referenzieren - letztendlich weniger Tipparbeit!

Die Erweiterung sieht dann so aus:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };

    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

Ressourcen in der Datei Enums.Resx sehen wie folgt aus ItemTypes_Movie : Film

Eine andere Sache, die ich gerne tue, ist, anstatt die Erweiterungsmethode direkt aufzurufen, rufe ich sie lieber mit einem @Html.EditorFor(x => x.MyProperty) auf, oder idealerweise habe ich einfach das ganze Formular in einem einzigen @Html.EditorForModel(). Um dies zu tun, ändere ich die String-Vorlage wie folgt

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

Wenn Sie sich dafür interessieren, habe ich hier in meinem Blog eine viel ausführlichere Antwort veröffentlicht:

http://paulthecyclist.com/2013/05/24/enum-dropdown/

6voto

nootn Punkte 851

Ich bin sehr spät dran, aber ich habe gerade eine wirklich coole Möglichkeit gefunden, dies mit einer Zeile Code zu tun, wenn Sie glücklich sind, die Unbeschränkte Melodie NuGet-Paket (eine schöne, kleine Bibliothek von Jon Skeet).

Diese Lösung ist besser, weil:

  1. Es wird sichergestellt (mit generischen Typbeschränkungen), dass der Wert wirklich ein Enum-Wert ist (aufgrund von Unconstrained Melody)
  2. Unnötiges Boxen wird vermieden (aufgrund der unbeschränkten Melodie)
  3. Alle Beschreibungen werden zwischengespeichert, um die Verwendung von Reflexion bei jedem Aufruf zu vermeiden (aufgrund von Unconstrained Melody)
  4. Es ist weniger Code als bei den anderen Lösungen!

Hier sind also die Schritte, um dies zu erreichen:

  1. In der Konsole des Paketmanagers "Install-Package UnconstrainedMelody".
  2. Fügen Sie eine Eigenschaft zu Ihrem Modell hinzu:

    //Replace "YourEnum" with the type of your enum
    public IEnumerable<SelectListItem> AllItems
    {
        get
        {
            return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
        }
    }

Nun, da Sie die Liste von SelectListItem in Ihrem Modell exponiert haben, können Sie @Html.DropDownList oder @Html.DropDownListFor mit dieser Eigenschaft als Quelle verwenden.

0 Stimmen

+1 für die Verwendung des Codes von Jon Skeet :), nur ein Scherz aber gut

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