Ich versuche, die Erweiterungsmethode Html.DropDownList
zu verwenden, kann aber nicht herausfinden, wie sie mit einer Aufzählung verwendet wird.
Nehmen wir an, ich habe eine Aufzählung wie diese:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
Wie erstelle ich ein Dropdown-Menü mit diesen Werten mithilfe der Erweiterungsmethode Html.DropDownList
?
Oder ist es meine beste Wahl, einfach eine for-Schleife zu erstellen und die HTML-Elemente manuell zu erstellen?
@Html.EnumDropDownListFor(
x => x.YourEnumField,
"Select My Type",
new { @class = "form-control" })
@Html.DropDownList("MyType",
EnumHelper.GetSelectList(typeof(MyType)) ,
"Select My Type",
new { @class = "form-control" })
Ich habe Runes Antwort in eine Erweiterungsmethode gerollt:
namespace MyApp.Common
{
public static class MyExtensions{
public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
where TEnum : struct, IComparable, IFormattable, IConvertible
{
var values = from TEnum e in Enum.GetValues(typeof(TEnum))
select new { Id = e, Name = e.ToString() };
return new SelectList(values, "Id", "Name", enumObj);
}
}
}
So können Sie schreiben:
ViewData["taskStatus"] = task.Status.ToSelectList();
von using MyApp.Common
Ich weiß, dass ich zu spät zur Party komme, aber ich dachte, Sie finden diese Variante vielleicht nützlich, da Sie hier auch beschreibende Zeichenfolgen anstelle von Aufzählungskonstanten in der Dropdown-Liste verwenden können. Verzieren Sie dazu jeden Aufzählungseintrag mit einem Attribut [System.ComponentModel.Description].
Zum Beispiel:
public enum TestEnum
{
[Description("Full test")]
FullTest,
[Description("Incomplete or partial test")]
PartialTest,
[Description("No test performed")]
None
}
Hier ist mein Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;
...
private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
{
Type realModelType = modelMetadata.ModelType;
Type underlyingType = Nullable.GetUnderlyingType(realModelType);
if (underlyingType != null)
{
realModelType = underlyingType;
}
return realModelType;
}
private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };
public static string GetEnumDescription<TEnum>(TEnum 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();
}
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
return EnumDropDownListFor(htmlHelper, expression, null);
}
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = from value in values
select new SelectListItem
{
Text = GetEnumDescription(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
};
// If the enum is nullable, add an 'empty' item to the collection
if (metadata.IsNullableValueType)
items = SingleEmptyItem.Concat(items);
return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
}
Sie können dies dann aus Ihrer Sicht tun:
@Html.EnumDropDownListFor(model => model.MyEnumProperty)
Hoffe das hilft dir!
** BEARBEITEN 2014-JAN-23: Microsoft hat gerade MVC 5.1 veröffentlicht, das jetzt über eine EnumDropDownListFor-Funktion verfügt. Leider scheint das Attribut [Description] nicht berücksichtigt zu werden, sodass der obige Code weiterhin gültig ist. Siehe Abschnitt Enum in Microsoft-Versionshinweise für MVC 5.1.
Update: Es unterstützt das Display Attribut [Display(Name = "Sample")]
, also kann man das benutzen.
[Update - habe dies gerade bemerkt und der Code sieht aus wie eine erweiterte Version des Codes hier: https://blogs.msdn.Microsoft.com/stuartleeks/2010/05/21/asp-net-mvc- Erstellen einer Dropdown-Liste-Helfer-für-Aufzählungen / , mit ein paar Ergänzungen. Wenn ja, erscheint die Zuschreibung fair ;-)]
In ASP.NET MVC 5.1 wurde der EnumDropDownListFor()
-Hilfer hinzugefügt, sodass keine benutzerdefinierten Erweiterungen erforderlich sind:
Modell :
public enum MyEnum
{
[Display(Name = "First Value - desc..")]
FirstValue,
[Display(Name = "Second Value - desc...")]
SecondValue
}
Ansicht :
@Html.EnumDropDownListFor(model => model.MyEnum)
Verwenden von Tag Helper (ASP.NET MVC 6) :
<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
Ich bin auf dasselbe Problem gestoßen, habe diese Frage gefunden und dachte, dass die Lösung von Ash nicht das ist, wonach ich gesucht habe. Das HTML selbst erstellen zu müssen, bedeutet weniger Flexibilität als die eingebaute Funktion Html.DropDownList()
.
Es stellte sich heraus, dass C # 3 usw. dies ziemlich einfach macht. Ich habe ein enum
mit dem Namen TaskStatus
:
var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
select new { ID = s, Name = s.ToString() };
ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);
Dadurch wird ein gutes altes SelectList
erstellt, das so verwendet werden kann, wie Sie es in der Ansicht gewohnt sind:
<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>
Die anonyme Art und LINQ macht dies IMHO so viel eleganter. Nichts für ungut, Ash. :)
Hier ist eine besser gekapselte Lösung:
https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5
Angenommen, hier ist Ihr Modell:
Beispielnutzung:
Generierte Benutzeroberfläche:
und generiertes HTML
Die Momentaufnahme des Quellcodes der Helper-Erweiterung:
Sie können das Beispielprojekt über den von mir bereitgestellten Link herunterladen.
EDIT: Hier ist der Code:
public static class EnumEditorHtmlHelper
{
/// <summary>
/// Creates the DropDown List (HTML Select Element) from LINQ
/// Expression where the expression returns an Enum type.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="expression">The expression.</param>
/// <returns></returns>
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression)
where TModel : class
{
TProperty value = htmlHelper.ViewData.Model == null
? default(TProperty)
: expression.Compile()(htmlHelper.ViewData.Model);
string selected = value == null ? String.Empty : value.ToString();
return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
}
/// <summary>
/// Creates the select list.
/// </summary>
/// <param name="enumType">Type of the enum.</param>
/// <param name="selectedItem">The selected item.</param>
/// <returns></returns>
private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
{
return (from object item in Enum.GetValues(enumType)
let fi = enumType.GetField(item.ToString())
let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
select new SelectListItem
{
Value = item.ToString(),
Text = title,
Selected = selectedItem == item.ToString()
}).ToList();
}
}
Für Html.DropDownListFor ist nur ein IEnumerable erforderlich. Eine Alternative zu Prises Lösung lautet daher wie folgt. So können Sie einfach schreiben:
@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())
[Wobei SelectedItemType ein Feld in Ihrem Modell vom Typ ItemTypes ist und Ihr Modell nicht null ist]
Außerdem müssen Sie die Erweiterungsmethode nicht wirklich generieren, da Sie enumValue.GetType () anstelle von typeof (T) verwenden können.
BEARBEITEN: Integrierte auch hier die Lösung von Simon und integrierte die ToDescription-Erweiterungsmethode.
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();
}
}
Also ohne Extension-Funktionen, wenn Sie einfach und unkompliziert suchen .. Das habe ich getan
<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>
dabei ist XXXXX.Sites.YYYY.Models.State eine Aufzählung
Wahrscheinlich ist es besser, die Helferfunktion auszuführen, aber wenn die Zeit knapp ist, wird dies die Arbeit erledigen.
Wenn Sie möchten, dass das value-Attribut Ihrer Auswahllistenelemente dem ganzzahligen Wert des Aufzählungstyps und nicht dem Zeichenfolgenwert zugeordnet wird, verwenden Sie den folgenden Code, um die Antworten von Prize und Rune zu erweitern:
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 Wert ohne Box zu erhalten.
Anmerkung: Ich habe auch eine generische Typeinschränkung hinzugefügt, um die Typen, für die diese Erweiterung verfügbar ist, nur auf Strukturen (Enums Basistyp) zu beschränken, und eine Laufzeit-Typüberprüfung, die sicherstellt, dass die übergebene Struktur gültig ist in der Tat eine Aufzählung.
pdate 23.10.12: Generischer Typparameter für zugrunde liegenden Typ hinzugefügt und Nicht-Kompilierungsproblem behoben, das .NET 4+ betrifft.
Die beste Lösung, die ich dafür gefunden habe, war dieses Blog mit Simon Goldstones Antwort zu kombinieren.
Dies ermöglicht die Verwendung der Aufzählung im Modell. Im Wesentlichen besteht die Idee darin, eine Ganzzahleigenschaft sowie die Aufzählung zu verwenden und die Ganzzahleigenschaft zu emulieren.
Verwenden Sie dann das Attribut [System.ComponentModel.Description], um das Modell mit Ihrem Anzeigetext zu versehen, und verwenden Sie in Ihrer Ansicht die Erweiterung "EnumDropDownListFor".
Dies macht sowohl die Ansicht als auch das Modell sehr gut lesbar und wartbar.
Modell:
public enum YesPartialNoEnum
{
[Description("Yes")]
Yes,
[Description("Still undecided")]
Partial,
[Description("No")]
No
}
//........
[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
get { return (Nullable<int>)CuriousQuestion; }
set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}
Aussicht:
@using MyProject.Extensions
{
//...
@Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}
Erweiterung (direkt von Antwort von Simon Goldstone , der Vollständigkeit halber hier eingeschlossen):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
using System.Web.Mvc.Html;
namespace MyProject.Extensions
{
//Extension methods must be defined in a static class
public static class MvcExtensions
{
private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
{
Type realModelType = modelMetadata.ModelType;
Type underlyingType = Nullable.GetUnderlyingType(realModelType);
if (underlyingType != null)
{
realModelType = underlyingType;
}
return realModelType;
}
private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };
public static string GetEnumDescription<TEnum>(TEnum 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();
}
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
return EnumDropDownListFor(htmlHelper, expression, null);
}
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = from value in values
select new SelectListItem
{
Text = GetEnumDescription(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
};
// If the enum is nullable, add an 'empty' item to the collection
if (metadata.IsNullableValueType)
items = SingleEmptyItem.Concat(items);
return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
}
}
}
Lösen des Problems, dass die Nummer anstelle von Text mithilfe der Prise-Erweiterungsmethode abgerufen wird.
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);
}
Ein super einfacher Weg, dies zu erledigen - ohne all das Erweiterungsmaterial, das übertrieben zu sein scheint, ist dieser:
Ihre Aufzählung:
public enum SelectedLevel
{
Level1,
Level2,
Level3,
Level4
}
Binden Sie die Enumeration in Ihrem Controller an eine Liste:
List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();
Danach werfen Sie es in einen ViewBag:
ViewBag.RequiredLevel = new SelectList(myLevels);
Schließlich binden Sie es einfach an die Ansicht:
@Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })
Dies ist bei weitem der einfachste Weg, den ich gefunden habe, und erfordert keine Erweiterungen oder etwas Verrücktes.
UPDATE: Siehe Andrews Kommentar unten.
Sie möchten etwas wie Enum.GetValues
verwenden
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
Dies sind Rune & Prize-Antworten, die so geändert wurden, dass der Wert Enum int
als ID verwendet wird.
Beispiel Enum:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
Verlängerungsmethode:
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()));
}
Anwendungsbeispiel:
<%= Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>
Denken Sie daran, den Namespace zu importieren, der die Extension-Methode 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, mit dem Sie ToSelectList
aufrufen, das ausgewählte Element ist.
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)
Diese Funktion wird ab sofort in MVC 5.1 über @Html.EnumDropDownListFor()
unterstützt.
Überprüfen Sie den folgenden Link:
https://docs.Microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum
Es ist wirklich schade, dass Microsoft 5 Jahre gebraucht hat, um ein solches Feature zu implementieren, das laut obiger Abstimmung so gefragt ist!
Nun, ich bin wirklich zu spät zur Party, aber für das, was es wert ist, habe ich über genau dieses Thema gebloggt, wobei ich eine EnumHelper
-Klasse erstelle, die eine sehr einfache Transformation ermöglicht.
http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%2
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);
Ihrer Ansicht nach:
@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() });
}
}
Aufbauend auf der Antwort von Simon besteht ein ähnlicher Ansatz darin, die Enum-Werte aus einer Ressourcendatei anstelle eines Beschreibungsattributs in der Enum-Datei selbst anzuzeigen. Dies ist hilfreich, wenn Ihre Website in mehr als einer Sprache gerendert werden muss und wenn Sie eine bestimmte Ressourcendatei für Enums haben, können Sie noch einen Schritt weiter gehen und nur Enum-Werte in Ihrer Enum-Datei haben und sie aus der Erweiterung von referenzieren eine Konvention wie [EnumName] _ [EnumValue] - letztendlich weniger tippen!
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 Enums.Resx-Datei sehen aus wie ItemTypes_Movie: Film
Eine andere Sache, die ich gerne mache, ist, anstatt die Erweiterungsmethode direkt aufzurufen, sie lieber mit einem @ Html.EditorFor (x => x.MyProperty) aufzurufen oder im Idealfall nur die gesamte Form in einem ordentlichen @ zu haben. Html.EditorForModel (). Dazu ändere ich das String Template so, dass es so aussieht
@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 dich das interessiert, habe ich hier auf meinem Blog eine viel ausführlichere Antwort veröffentlicht:
Ich bin sehr spät dran, aber ich habe gerade einen wirklich coolen Weg gefunden, dies mit einer Codezeile zu tun, wenn Sie glücklich sind, das Paket nconstrained Melody NuGet (eine nette, kleine Bibliothek von Jon) hinzuzufügen Skeet).
Diese Lösung ist besser, weil:
Also, hier sind die Schritte, um dies zum Laufen zu bringen:
Fügen Sie Ihrem Modell eine Eigenschaft wie folgt 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() });
}
}
Nachdem Sie die Liste von SelectListItem in Ihrem Modell verfügbar gemacht haben, können Sie die @ Html.DropDownList oder @ Html.DropDownListF verwenden, um diese Eigenschaft als Quelle zu verwenden.
Ich habe eine Antwort gefunden hier . Einige meiner Aufzählungen haben jedoch das Attribut [Description(...)]
, daher habe ich den Code geändert, um dies zu unterstützen:
enum Abc
{
[Description("Cba")]
Abc,
Def
}
public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
{
IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
.Cast<TEnum>();
List<SelectListItem> items = new List<SelectListItem>();
foreach (var value in values)
{
string text = value.ToString();
var member = typeof(TEnum).GetMember(value.ToString());
if (member.Count() > 0)
{
var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (customAttributes.Count() > 0)
{
text = ((DescriptionAttribute)customAttributes[0]).Description;
}
}
items.Add(new SelectListItem
{
Text = text,
Value = value.ToString(),
Selected = (value.Equals(selectedValue))
});
}
return htmlHelper.DropDownList(
name,
items
);
}
Ich hoffe, das hilft.
In .NET Core können Sie einfach Folgendes verwenden:
@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())
Sie können auch meine benutzerdefinierten HtmlHelper in Griffin.MvcContrib verwenden. Der folgende Code:
@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />
Erzeugt:
Wenn Sie die Lokalisierungsunterstützung hinzufügen möchten, ändern Sie einfach die s.toString () -Methode in etwa wie folgt:
ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
select new { ID = s, Name = rManager.GetString(s.ToString()) };
In diesem Beispiel ist typeof (Resources) die Ressource, die Sie laden möchten. Anschließend erhalten Sie die lokalisierte Zeichenfolge. Dies ist auch nützlich, wenn Ihr Enumerator Werte mit mehreren Wörtern enthält.
Dies ist meine Version der Hilfsmethode. Ich benutze das:
var values = from int e in Enum.GetValues(typeof(TEnum))
select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };
Stattdessen:
var values = from TEnum e in Enum.GetValues(typeof(TEnum))
select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
, Name = e.ToString() };
Hier ist es:
public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
{
throw new ArgumentException("self must be enum", "self");
}
Type t = typeof(TEnum);
var values = from int e in Enum.GetValues(typeof(TEnum))
select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };
return new SelectList(values, "ID", "Name", self);
}
Ein weiterer Fix für diese Erweiterungsmethode: In der aktuellen Version wurde der aktuelle Wert der Aufzählung nicht ausgewählt. Ich habe die letzte Zeile gefixt:
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()
};
return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
}
Ich möchte diese Frage auf eine andere Weise beantworten, bei der der Benutzer nichts in den Ausdrücken controller
oder Linq
tun muss. Diesen Weg...
Ich habe ein ENUM
public enum AccessLevelEnum
{
/// <summary>
/// The user cannot access
/// </summary>
[EnumMember, Description("No Access")]
NoAccess = 0x0,
/// <summary>
/// The user can read the entire record in question
/// </summary>
[EnumMember, Description("Read Only")]
ReadOnly = 0x01,
/// <summary>
/// The user can read or write
/// </summary>
[EnumMember, Description("Read / Modify")]
ReadModify = 0x02,
/// <summary>
/// User can create new records, modify and read existing ones
/// </summary>
[EnumMember, Description("Create / Read / Modify")]
CreateReadModify = 0x04,
/// <summary>
/// User can read, write, or delete
/// </summary>
[EnumMember, Description("Create / Read / Modify / Delete")]
CreateReadModifyDelete = 0x08,
/*/// <summary>
/// User can read, write, or delete
/// </summary>
[EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
CreateReadModifyDeleteVerify = 0x16*/
}
Jetzt kann ich einfach ein dropdown
erstellen, indem ich dieses enum
verwende.
@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })
OR
@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })
Wenn Sie einen Index auswählen möchten, versuchen Sie dies
@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })
Hier habe ich AccessLevelEnum.NoAccess
als zusätzlichen Parameter für die Standardauswahl des Dropdowns verwendet.
@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem>
{
new SelectListItem { Text = "----Select----", Value = "-1" },
new SelectListItem { Text = "Marrid", Value = "M" },
new SelectListItem { Text = "Single", Value = "S" }
})
@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
new ListItem{Text="Male",Value="Male"},
new ListItem{Text="Female",Value="Female"},
new ListItem{Text="--- Select -----",Value="-----Select ----"}
}
)
Am Ende habe ich Erweiterungsmethoden erstellt, um das zu tun, was hier im Wesentlichen die akzeptierte Antwort ist. Die letzte Hälfte der Gist befasst sich speziell mit Enum.
Hier eine Martin Faartoft-Variante, in der Sie benutzerdefinierte Beschriftungen anbringen können, die sich gut zur Lokalisierung eignen.
public static class EnumHtmlHelper
{
public static SelectList ToSelectList<TEnum>(this TEnum enumObj, Dictionary<int, string> customLabels)
where TEnum : struct, IComparable, IFormattable, IConvertible
{
var values = from TEnum e in Enum.GetValues(typeof(TEnum))
select new { Id = e, Name = customLabels.First(x => x.Key == Convert.ToInt32(e)).Value.ToString() };
return new SelectList(values, "Id", "Name", enumObj);
}
}
In Ansicht verwenden:
@Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary<int, string>() {
{ 1, ContactResStrings.FeedbackCategory },
{ 2, ContactResStrings.ComplainCategory },
{ 3, ContactResStrings.CommentCategory },
{ 4, ContactResStrings.OtherCategory }
}), new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Category)
//// ViewModel
public class RegisterViewModel
{
public RegisterViewModel()
{
ActionsList = new List<SelectListItem>();
}
public IEnumerable<SelectListItem> ActionsList { get; set; }
public string StudentGrade { get; set; }
}
//// Enum Class
public enum GradeTypes
{
A,
B,
C,
D,
E,
F,
G,
H
}
////Controller action
public ActionResult Student()
{
RegisterViewModel vm = new RegisterViewModel();
IEnumerable<GradeTypes> actionTypes = Enum.GetValues(typeof(GradeTypes))
.Cast<GradeTypes>();
vm.ActionsList = from action in actionTypes
select new SelectListItem
{
Text = action.ToString(),
Value = action.ToString()
};
return View(vm);
}
////// View Action
<div class="form-group">
<label class="col-lg-2 control-label" for="hobies">Student Grade:</label>
<div class="col-lg-10">
@Html.DropDownListFor(model => model.StudentGrade, Model.ActionsList, new { @class = "form-control" })
</div>
In MVC4 würde ich das gerne machen
@Html.DropDownList("RefType", new SelectList(Enum.GetValues(typeof(WebAPIApp.Models.RefType))), " Select", new { @class = "form-control" })
public enum RefType
{
Web = 3,
API = 4,
Security = 5,
FE = 6
}
public class Reference
{
public int Id { get; set; }
public RefType RefType { get; set; }
}
Ich habe folgendes gemacht und arbeite erfolgreich:
@model MyModel.cs
@Html.EnumDropDownListFor(m=>m.MyItemType )
public ItemTypes MyItemType { get; set; }
@ Simon Goldstone: Danke für deine Lösung, sie kann in meinem Fall perfekt angewendet werden. Das einzige Problem ist, dass ich es in VB übersetzen musste. Aber jetzt ist es geschafft und um anderen Zeit zu sparen (falls sie es brauchen), habe ich es hier abgelegt:
Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions
Public Module HtmlHelpers
Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
Dim realModelType = modelMetadata.ModelType
Dim underlyingType = Nullable.GetUnderlyingType(realModelType)
If Not underlyingType Is Nothing Then
realModelType = underlyingType
End If
Return realModelType
End Function
Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}
Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
Dim fi = value.GetType().GetField(value.ToString())
Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
Return attributes(0).Description
Else
Return value.ToString()
End If
End Function
<Extension()>
Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
Return EnumDropDownListFor(htmlHelper, expression, Nothing)
End Function
<Extension()>
Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
Dim enumType As Type = GetNonNullableModelType(metaData)
Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()
Dim items As IEnumerable(Of SelectListItem) = From value In values
Select New SelectListItem With
{
.Text = GetEnumDescription(value),
.Value = value.ToString(),
.Selected = value.Equals(metaData.Model)
}
' If the enum is nullable, add an 'empty' item to the collection
If metaData.IsNullableValueType Then
items = SingleEmptyItem.Concat(items)
End If
Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
End Function
End Module
Ende Du verwendest es so:
@Html.EnumDropDownListFor(Function(model) (model.EnumField))
1- Erstellen Sie Ihre ENUM
public enum LicenseType
{
xxx = 1,
yyy = 2
}
2- Erstellen Sie Ihre Serviceklasse
public class LicenseTypeEnumService
{
public static Dictionary<int, string> GetAll()
{
var licenseTypes = new Dictionary<int, string>();
licenseTypes.Add((int)LicenseType.xxx, "xxx");
licenseTypes.Add((int)LicenseType.yyy, "yyy");
return licenseTypes;
}
public static string GetById(int id)
{
var q = (from p in this.GetAll() where p.Key == id select p).Single();
return q.Value;
}
}
3- Stellen Sie den ViewBag in Ihrem Controller ein
var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");
4- Binden Sie Ihre DropDownList
@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)