Comment créer une dropdownlist à partir d'un enum dans ASP.NET MVC?
j'essaye d'utiliser la méthode d'extension Html.DropDownList
mais je ne peux pas comprendre comment l'utiliser avec une énumération.
disons que j'ai une énumération comme celle-ci:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
comment créer une liste déroulante avec ces valeurs en utilisant la méthode d'extension Html.DropDownList
?
ou mon meilleur pari est-il de simplement créer une boucle pour et créer les éléments Html manuellement?
30 réponses
pour MVC v5.1 utiliser Html.Enumdropdownlist for
@Html.EnumDropDownListFor(
x => x.YourEnumField,
"Select My Type",
new { @class = "form-control" })
Pour MVC v5 utilisation EnumHelper
@Html.DropDownList("MyType",
EnumHelper.GetSelectList(typeof(MyType)) ,
"Select My Type",
new { @class = "form-control" })
pour MVC 5 et inférieur
j'ai roulé Rune de réponse dans une extension de la méthode:
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);
}
}
}
cela vous permet d'écrire:
ViewData["taskStatus"] = task.Status.ToSelectList();
par using MyApp.Common
je sais que je suis en retard à la fête sur ce sujet, mais j'ai pensé que vous pourriez trouver cette variante utile, car celle-ci vous permet également d'utiliser des chaînes descriptives plutôt que des constantes d'énumération dans la chute vers le bas. Pour ce faire, décorez chaque entrée de recensement avec un [système.ComponentModel.Description] l'attribut.
par exemple:
public enum TestEnum
{
[Description("Full test")]
FullTest,
[Description("Incomplete or partial test")]
PartialTest,
[Description("No test performed")]
None
}
Voici mon 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);
}
vous pouvez alors le faire dans votre vue:
@Html.EnumDropDownListFor(model => model.MyEnumProperty)
J'espère que cela vous aidera!
**EDIT 2014-JAN-23: Microsoft viennent de publier MVC 5.1, qui dispose désormais d'une fonction EnumDropDownListFor. Malheureusement, il ne semble pas respecter l'attribut [Description] de sorte que le code ci-dessus tient toujours.Voir section Enum dans notes de version de Microsoft pour MVC 5.1.
mise à Jour: Il prend en charge le Affichage attribut [Display(Name = "Sample")]
si, on peut donc l'utiliser.
[mise à Jour - juste remarqué cela, et le code ressemble à une version étendue de la code ici: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/ , avec quelques ajouts. Si tel est le cas, l'attribution paraît équitable ; -)]
In ASP.NET MVC 5.1 , ils ont ajouté le EnumDropDownListFor()
helper, donc pas besoin d'extensions personnalisées:
Modèle :
public enum MyEnum
{
[Display(Name = "First Value - desc..")]
FirstValue,
[Display(Name = "Second Value - desc...")]
SecondValue
}
Vue :
@Html.EnumDropDownListFor(model => model.MyEnum)
utilisant L'aide D'étiquette (ASP.NET MVC 6) :
<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
je suis tombé sur le même problème, j'ai trouvé cette question, et j'ai pensé que la solution fournie par Ash n'était pas ce que je cherchais; avoir à créer le HTML moi-même signifie moins de flexibilité par rapport à la fonction intégrée Html.DropDownList()
.
S'avère C#3 etc. c'est assez facile. J'ai un enum
appelé 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);
Cela crée un bon vieux SelectList
qui peut être utilisé comme vous êtes habitué à la vue:
<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>
le type anonyme et LINQ rend cela beaucoup plus élégant IMHO. Aucune infraction, l'intention, de la Cendre. :)
Voici une meilleure solution encapsulée:
https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5
dites Voici votre modèle:
Exemple D'Utilisation:
UI générée:
et généré HTML
Le Helper Code Source de l'Extension snap shot:
vous pouvez télécharger le projet échantillon à partir du lien que j'ai fourni.
EDIT: voici le 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();
}
}
Html.DropDownListFor exige seulement un IEnumerable, ainsi une alternative à la solution de Prise est comme suit. Cela vous permettra d'écrire simplement:
@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())
[où SelectedItemType est un champ sur votre modèle de type ItemTypes, et votre modèle est non-null]
en outre, vous n'avez pas vraiment besoin de généraliser la méthode d'extension que vous pouvez utiliser enumValue.GetType () plutôt que typeof (T).
modifier: solution ici aussi, et inclus la méthode d'extension ToDescription.
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();
}
}
donc sans fonctions D'Extension si vous cherchez simple et facile.. C'est ce que j'ai fait
<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>
où XXXXX.Site.YYYY.Modèle.L'état est un enum
probablement mieux pour faire fonction d'aide, mais quand le temps est court cela fera le travail fait.
pour étendre les réponses de Prise et de Rune, si vous souhaitez que l'attribut valeur de votre liste select soit associé à la valeur entière du type D'énumération, plutôt qu'à la valeur de chaîne, utilisez le code suivant:
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);
}
au lieu de traiter chaque valeur D'énumération comme un objet de TEnum, nous pouvons la traiter comme un objet et ensuite la lancer à l'entier pour obtenir la valeur non boxée.
Note: J'ai aussi ajouté un type générique contrainte pour restreindre les types pour lesquels cette extension est disponible aux seules structures (type de base D'Enum), et une validation de type d'exécution qui garantit que la structure transmise est bien un Enum.
mise à Jour 10/23/12: Ajout d'un paramètre de type générique pour le type sous-jacent et d'un problème de non-compilation fixe affectant .NET 4+.
pour résoudre le problème d'obtenir le numéro au lieu du texte en utilisant la méthode d'extension de 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);
}
une façon très facile de faire cela-sans tous les trucs d'extension qui semble exagérée est celle-ci:
votre enum:
public enum SelectedLevel
{
Level1,
Level2,
Level3,
Level4
}
dans votre controller, liez L'Enum à une liste:
List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();
après cela, jetez-le dans un sac de vue:
ViewBag.RequiredLevel = new SelectList(myLevels);
finalement lient simplement à la vue:
@Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })
C'est de loin la façon la plus facile que j'ai trouvé et ne nécessite pas d'extensions ou quoi que ce soit d'aussi fou.
UPDATE : voir le commentaire de Andrews ci-dessous.
la meilleure solution que j'ai trouvée pour cela était de combiner ce blog avec réponse de Simon Goldstone .
Cela permet l'utilisation d'enum dans le modèle. Essentiellement l'idée est d'utiliser une propriété integer aussi bien que l'enum, et émuler la propriété integer.
utiliser ensuite le [System.ComponentModel.Description] attribut pour annoter le modèle avec votre texte d'affichage, et utiliser un " EnumDropDownListFor" extension de votre point de vue.
cela rend à la fois la vue et le modèle très lisible et maintenable.
Modèle:
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; }
}
:
@using MyProject.Extensions
{
//...
@Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}
Extension (directement à partir de Simon Goldstone la réponse de , inclus ici par souci d'exhaustivité):
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);
}
}
}
vous voulez regarder l'utilisation de quelque chose comme Enum.GetValues
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
ici Rune & Prise réponses modifiées pour utiliser la valeur Enum int
comme ID.
Échantillon Enum:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
"151970920 l'Extension de la méthode:
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()));
}
exemple d'usage:
<%= Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>
N'oubliez pas D'importer l'espace de noms contenant la méthode D'Extension
<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>
Exemple de code HTML généré:
<select id="MyEnumList" name="MyEnumList">
<option value="1">Movie</option>
<option selected="selected" value="2">Game</option>
<option value="3">Book </option>
</select>
noter que le point que vous utilisez pour appeler le ToSelectList
sur l'élément sélectionné.
C'est la version pour Rasoir:
@{
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)
maintenant cette fonctionnalité est prise en charge hors de la boîte dans MVC 5.1 à @Html.EnumDropDownListFor()
Vérifier le lien suivant:
https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum
il est vraiment dommage qu'il ait fallu 5 ans à Microsoft pour mettre en œuvre une telle fonctionnalité qui est si en demande selon le vote ci-dessus!
en S'appuyant sur la réponse de Simon, une approche similaire consiste à obtenir les valeurs Enum à afficher à partir d'un fichier de ressources, au lieu d'un attribut de description dans L'Enum lui-même. Ceci est utile si votre site doit être rendu dans plus d'une langue et si vous deviez avoir un fichier ressource spécifique pour Enums, vous pourriez aller un peu plus loin et avoir juste des valeurs Enum, dans votre Enum et les référencer à partir de l'extension par une convention telle que [EnumName]_[EnumValue] - en fin de compte moins de Dactylographie!
l'extension ressemble alors à:
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();
}
des Ressources dans les Énumérations.Le fichier Resx ressemble à ItemTypes_Movie: Film
une autre chose que j'aime faire est, au lieu d'appeler directement la méthode d'extension, je préfère l'appeler avec un @Html.EditorFor(x = > X. MyProperty), ou idéalement avoir juste la forme entière, dans un neat @Html.EditorForModel (). Pour ce faire, je change le modèle de chaîne de caractères pour ressembler à ceci
@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))
}
si cela vous intéresse, j'ai mis une réponse beaucoup plus détaillée ici sur mon blog:
Eh bien je suis vraiment en retard à la fête, mais pour ce que cela vaut, j'ai blogué sur ce sujet même par lequel je crée une classe EnumHelper
qui permet une transformation très facile.
http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23
dans votre contrôleur:
//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);
de votre point De Vue:
@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)
La classe helper:
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() });
}
}
je suis très en retard sur celui-ci, mais je viens de trouver une façon vraiment cool de le faire avec une ligne de code, si vous êtes heureux d'ajouter la mélodie non contrainte paquet NuGet (une belle, petite bibliothèque de Jon Skeet).
Cette solution est meilleure parce que:
- Il assure (avec le type générique, contraintes) que la valeur est une valeur d'enum (due à la Contrainte de la Mélodie)
- il évite inutile boxe (due à la Contrainte de la Mélodie)
- il cache toutes les descriptions pour éviter d'utiliser la réflexion sur chaque appel (en raison de la mélodie libre)
- C'est moins de code que les autres solutions!
Donc, voici les étapes pour obtenir ce travail:
- Dans Le Gestionnaire De Paquets De La Console, "Install-Package UnconstrainedMelody"
-
Ajouter une propriété sur votre modèle comme:
//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() }); } }
maintenant que vous avez la liste de Sélectlistitem exposée sur votre modèle, vous pouvez utiliser le @Html.DropDownList ou @Html.Dropdownlistpour utiliser cette propriété comme source.
une autre correction à cette méthode d'extension - la version courante n'a pas sélectionné la valeur courante de l'enum. J'ai corrigé la dernière ligne:
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());
}
si vous voulez ajouter le support de localisation, changez simplement le S. ToString () méthode à quelque chose comme ceci:
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()) };
ici la typeof(Resources) est la ressource que vous voulez charger, et ensuite vous obtenez la chaîne localisée, également utile si votre énumérateur a des valeurs avec des mots multiples.
C'est ma version de la méthode helper. J'utilise ceci:
var values = from int e in Enum.GetValues(typeof(TEnum))
select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };
au lieu de cela:
var values = from TEnum e in Enum.GetValues(typeof(TEnum))
select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
, Name = e.ToString() };
le voici:
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);
}
vous pouvez également utiliser mes Helpers HTML personnalisés dans Griffin.MvcContrib. Le code suivant:
@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />
génère:
j'ai trouvé une réponse ici . Cependant, certains de mes enums ont l'attribut [Description(...)]
, donc j'ai modifié le code pour fournir le support pour cela:
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
);
}
Espère que ça aide.
@Simon Goldstone: Merci pour votre solution, elle peut être parfaitement appliquée dans mon cas. Le seul problème, c'est que j'ai dû le traduire en VB. Mais maintenant c'est fait et pour sauver le temps des autres (au cas où ils en auraient besoin) je le mets ici:
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
fin vous l'utilisez comme ceci:
@Html.EnumDropDownListFor(Function(model) (model.EnumField))
j'ai fini par créer des méthodes d'extension pour faire ce qui est essentiellement la réponse accepter ici. La dernière moitié du Gist traite spécifiquement D'Enum.
@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 ----"}
}
)
@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" }
})
ici une variation de Martin Faartoft où vous pouvez mettre des étiquettes personnalisées qui est agréable pour la localisation.
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);
}
}
utilisation en vue:
@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)
j'ai fait ce qui suit et travaille avec succès:
- Dans la vue.cshtml:
@modèle Monmodèle.cs
@Html.EnumDropDownListFor(m=>m.MyItemType )
- dans le modèle: Monmodèle.cs
public ItemTypes MyItemType { get; set; }