J'essaie d'utiliser la méthode d'extension Html.DropDownList
mais je ne vois pas 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 un menu déroulant avec ces valeurs à l'aide de la méthode d'extension Html.DropDownList
?
Ou est-il préférable de simplement créer une boucle for et de créer les éléments HTML manuellement?
@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" })
J'ai transformé la réponse de Rune en une méthode d'extension:
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, mais je pense que cette variante pourrait être utile, car elle vous permet également d'utiliser des chaînes descriptives plutôt que des constantes d'énumération dans le menu déroulant. Pour ce faire, décorez chaque entrée d'énumération avec un attribut [System.ComponentModel.Description].
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 à votre avis:
@Html.EnumDropDownListFor(model => model.MyEnumProperty)
J'espère que cela vous aide!
** EDIT 2014-JAN-23: Microsoft vient de publier MVC 5.1, qui possède désormais une fonctionnalité EnumDropDownListFor. Malheureusement, il ne semble pas respecter l'attribut [Description], aussi le code ci-dessus est-il toujours valide. Voir section Enum dans Notes de publication de Microsoft pour MVC 5.1.
Update: Il supporte l'attribut Display[Display(Name = "Sample")]
, donc on peut l'utiliser.
[Mise à jour - je viens de le remarquer et le code ressemble à une version étendue du code ici: https://blogs.msdn.Microsoft.com/stuartleeks/2010/05/21/asp-net-mvc- creation-a-dropdownlist-helper-for-enums / , avec quelques ajouts. Si oui, l'attribution semblerait juste ;-)]
Dans ASP.NET MVC 5.1, ils ont ajouté le helper EnumDropDownListFor()
, vous n'avez donc pas besoin d'extensions personnalisées:
Modèle :
public enum MyEnum
{
[Display(Name = "First Value - desc..")]
FirstValue,
[Display(Name = "Second Value - desc...")]
SecondValue
}
Voir :
@Html.EnumDropDownListFor(model => model.MyEnum)
à l'aide de Tag Helper (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 je pensais que la solution fournie par Ash n'était pas ce que je cherchais; Le fait de créer moi-même le code HTML signifie moins de flexibilité que la fonction intégrée Html.DropDownList()
.
Il s'avère que C # 3 etc. rend cela 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 en avez l'habitude dans la vue:
<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>
Le type anonyme et LINQ rendent cet IMHO beaucoup plus élégant. Aucune infraction prévue, Ash. :)
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:
Interface utilisateur générée:
Et HTML généré
La capture instantanée de code source du Helper Extension:
Vous pouvez télécharger l'exemple de projet à 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 ne requiert qu'un IEnumerable, une alternative à la solution de Prise est donc la suivante. 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-nul]
De plus, vous n'avez pas vraiment besoin de générer la méthode d'extension, car vous pouvez utiliser enumValue.GetType () plutôt que typeof (T).
EDIT: La solution de Simon a également été intégrée ici, ainsi que 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 recherchez 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.Sites.YYYY.Models.State est un enum
Il est probablement préférable d’utiliser la fonction d’assistance, mais lorsque le temps est compté, le travail est fait.
En développant les réponses Prize et Rune, si vous souhaitez que l'attribut value de vos éléments de la liste de sélection soit mis en correspondance avec la valeur entière du type Enumeration, plutôt que la valeur de la 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 TEnum, nous pouvons le traiter comme un objet, puis le convertir en entier pour obtenir la valeur non encadrée.
Remarque: J'ai également ajouté une contrainte de type générique pour limiter les types pour lesquels cette extension est disponible à des structures uniquement (type de base d'Enum), ainsi qu'une validation de type à l'exécution garantissant que la structure transmise est En effet, un Enum.
Mise à jour le 23/10/12: Ajout d'un paramètre de type générique pour le type sous-jacent et un problème résolu de non-compilation affectant .NET 4+.
La meilleure solution que j'ai trouvée pour cela consistait à combiner ce blog avec réponse de Simon Goldstone .
Cela permet d'utiliser l'énum dans le modèle. L'idée est essentiellement d'utiliser une propriété entière ainsi que l'énumération et d'émuler la propriété entière.
Utilisez ensuite l'attribut [System.ComponentModel.Description] pour annoter le modèle avec votre texte d'affichage et utilisez une extension "EnumDropDownListFor" dans votre vue.
Cela rend la vue et le modèle très lisibles et maintenables.
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; }
}
Vue:
@using MyProject.Extensions
{
//...
@Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}
Extension (directement de réponse de Simon Goldstone , incluse ici pour complément):
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);
}
}
}
Pour résoudre le problème de l'obtention du numéro au lieu du texte, utilisez 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);
}
Un moyen très facile de faire cela - sans toutes les extensions qui semblent excessives est la suivante:
Votre enum:
public enum SelectedLevel
{
Level1,
Level2,
Level3,
Level4
}
À l’intérieur de votre contrôleur, liez l’énumération à une liste:
List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();
Après cela, jetez-le dans un ViewBag:
ViewBag.RequiredLevel = new SelectList(myLevels);
Enfin, simplement le lier à la vue:
@Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })
C'est de loin le moyen le plus simple que j'ai trouvé et qui ne nécessite aucune extension ou quoi que ce soit de fou.
UPDATE: Voir le commentaire Andrews ci-dessous.
Vous voulez utiliser quelque chose comme Enum.GetValues
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
Les réponses de Rune & Prize ont été modifiées pour utiliser la valeur Enum int
en tant qu'ID.
Exemple d'énumération:
public enum ItemTypes
{
Movie = 1,
Game = 2,
Book = 3
}
Méthode d'extension:
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'utilisation:
<%= 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 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>
Notez que l’élément que vous utilisez pour appeler ToSelectList
est l’élément sélectionné.
Ceci est la version pour 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)
Désormais, cette fonctionnalité est prise en charge dans MVC 5.1 via @Html.EnumDropDownListFor()
Vérifiez 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 oeuvre une telle fonctionnalité, très demandée par le vote ci-dessus!
Eh bien, je suis vraiment en retard pour la fête, mais pour ce que cela vaut, j’ai écrit un blog sur ce sujet même dans 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-enen-in-mvc-and-c%2
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);
Dans votre vue:
@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)
La classe d'assistance:
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() });
}
}
S'appuyant sur la réponse de Simon, une approche similaire consiste à obtenir les valeurs Enum à afficher à partir d'un fichier de ressources, plutôt que dans un attribut description au sein de l'énum lui-même. Ceci est utile si votre site doit être restitué dans plusieurs langues et si vous aviez un fichier de ressources spécifique pour Enums, vous pourriez aller plus loin et ne placer que des valeurs Enum dans votre énumération et les référencer depuis l'extension par une convention telle que [EnumName] _ [EnumValue] - finalement moins de frappe!
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();
}
Ressources dans le fichier Enums.Resx ressemblant à ItemTypes_Movie: Film
Une autre chose que j'aime faire est qu'au lieu d'appeler directement la méthode d'extension, je l'appellerais plutôt avec un @ Html.EditorFor (x => x.MyProperty) ou, idéalement, tout le formulaire, dans un @ Html.EditorForModel (). Pour ce faire, je modifie le modèle de chaîne pour qu'il ressemble à 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:
Je suis très en retard sur celui-ci, mais je viens de trouver un moyen vraiment cool de le faire avec une seule ligne de code, si vous êtes heureux d'ajouter le package nconstrained Melody NuGet (une jolie petite bibliothèque de Jon Skeet).
Cette solution est meilleure car:
Alors, voici les étapes pour que cela fonctionne:
Ajoutez une propriété sur votre modèle comme ceci:
//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 des SelectListItem exposée sur votre modèle, vous pouvez utiliser @ Html.DropDownList ou @ Html.DropDownListFor en utilisant cette propriété comme source.
J'ai trouvé une réponse ici . Cependant, certaines de mes énumérations ont l'attribut [Description(...)]
, j'ai donc modifié le code pour fournir un 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
);
}
J'espère que ça t'as aidé.
Dans .NET Core, vous pouvez simplement utiliser ceci:
@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())
Vous pouvez également utiliser mes HtmlHelpers 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:
Si vous souhaitez ajouter un support de localisation, modifiez simplement la méthode s.toString () comme suit:
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, le typeof (Ressources) est la ressource que vous voulez charger, puis vous obtenez la chaîne localisée, également utile si votre énumérateur a des valeurs avec plusieurs mots.
Ceci est ma version de la méthode d'assistance. 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:
var values = from TEnum e in Enum.GetValues(typeof(TEnum))
select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
, Name = e.ToString() };
C'est ici:
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);
}
Un autre correctif pour cette méthode d'extension - la version actuelle n'a pas sélectionné la valeur actuelle de l'énum. 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());
}
Je voudrais répondre à cette question différemment, l'utilisateur ne doit rien faire dans l'expression controller
ou Linq
. Par ici...
J'ai un 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*/
}
Maintenant, je peux simplement créer un dropdown
en utilisant ce enum
.
@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" })
Si vous voulez faire un index sélectionné, essayez ceci
@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })
Ici, j'ai utilisé AccessLevelEnum.NoAccess
comme paramètre supplémentaire pour la sélection par défaut du menu déroulant.
@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 ----"}
}
)
J'ai fini par créer des méthodes d'extention pour faire ce qui est essentiellement la réponse acceptée ici. La dernière moitié du Gist traite spécifiquement d’Enum.
Voici une variante de Martin Faartoft où vous pouvez mettre des étiquettes personnalisées, ce qui est bien 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);
}
}
Utiliser 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)
//// 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>
Dans MVC4, je voudrais faire comme ceci
@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; }
}
J'ai fait ce qui suit et fonctionne avec succès:
@model MyModel.cs
@Html.EnumDropDownListFor(m=>m.MyItemType )
public ItemTypes MyItemType { get; set; }
@Simon Goldstone: Merci pour votre solution, elle peut parfaitement être appliquée dans mon cas. Le seul problème est que je devais 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))
1- Créez votre ENUM
public enum LicenseType
{
xxx = 1,
yyy = 2
}
2- Créez votre classe de service
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- Placez le ViewBag dans votre contrôleur
var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");
4- Liez votre DropDownList
@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)