Lier un Enum à une DropDownList dans MVC 4? [dupliquer]
cette question a déjà une réponse ici:
- comment créer une dropdownlist à partir d'un enum dans ASP.NET MVC? 36 réponses
j'ai trouvé partout que le moyen commun de lier les Énums aux chutes est par les méthodes d'aide, qui semble un peu exagéré pour une tâche si simple en apparence.
Quelle est la meilleure façon de lier les enum à DropDownLists en ASP.Net MVC 4?
7 réponses
je pense qu'il s'agit de la seule voie (propre), ce qui est dommage, mais au moins il ya quelques options là-bas. Je recommande d'avoir un oeil à ce blog: http://paulthecyclist.com/2013/05/24/enum-dropdown/
Désolé, c'est trop long à copier ici, mais l'essentiel est qu'il a créé une nouvelle méthode HTML helper pour cela.
tout le code source est disponible sur GitHub .
vous pouvez à ceci:
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
Enums sont soutenus par le cadre depuis MVC 5.1:
@Html.EnumDropDownListFor(m => m.Palette)
texte affiché peut être personnalisé:
public enum Palette
{
[Display(Name = "Black & White")]
BlackAndWhite,
Colour
}
lien MSDN: http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum
dans mon contrôleur:
var feedTypeList = new Dictionary<short, string>();
foreach (var item in Enum.GetValues(typeof(FeedType)))
{
feedTypeList.Add((short)item, Enum.GetName(typeof(FeedType), item));
}
ViewBag.FeedTypeList = new SelectList(feedTypeList, "Key", "Value", feed.FeedType);
de mon point De Vue:
@Html.DropDownList("FeedType", (SelectList)ViewBag.FeedTypeList)
la solution de PaulTheCyclist est en place. Mais je n'utiliserais pas RESX (je devrais ajouter un nouveau .fichier resx pour chaque nouvel enum??)
Voici mon expression HtmlHelper:
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression, object attributes = null)
{
//Get metadata from enum
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var enumType = GetNonNullableModelType(metadata);
var values = Enum.GetValues(enumType).Cast<TEnum>();
//Convert enumeration items into SelectListItems
var items =
from value in values
select new SelectListItem
{
Text = value.ToDescription(),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
};
//Check for nullable value types
if (metadata.IsNullableValueType)
{
var emptyItem = new List<SelectListItem>
{
new SelectListItem {Text = string.Empty, Value = string.Empty}
};
items = emptyItem.Concat(items);
}
//Return the regular DropDownlist helper
return htmlHelper.DropDownListFor(expression, items, attributes);
}
Voici comment je déclare mes énums:
[Flags]
public enum LoanApplicationType
{
[Description("Undefined")]
Undefined = 0,
[Description("Personal Loan")]
PersonalLoan = 1,
[Description("Mortgage Loan")]
MortgageLoan = 2,
[Description("Vehicle Loan")]
VehicleLoan = 4,
[Description("Small Business")]
SmallBusiness = 8,
}
et voici l'appel D'une vue de rasoir:
<div class="control-group span2">
<div class="controls">
@Html.EnumDropDownListFor(m => m.LoanType, new { @class = "span2" })
</div>
</div>
où @Model.LoanType
est une propriété modèle du type de prêt
mise à JOUR: Désolé, j'ai oublié d'inclure le code pour la fonction d'assistance ToDescription()
/// <summary>
/// Returns Description Attribute information for an Enum value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ToDescription(this Enum value)
{
if (value == null)
{
return string.Empty;
}
var attributes = (DescriptionAttribute[]) value.GetType().GetField(
Convert.ToString(value)).GetCustomAttributes(typeof (DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : Convert.ToString(value);
}
techniquement, vous n'avez pas besoin d'une méthode d'aide, puisque Html.DropdownListFor
nécessite seulement un SelectList
ou Ienumerable<SelectListItem>
. Vous pouvez simplement transformer vos enums en une telle sortie et l'alimenter de cette façon.
j'utilise une méthode de bibliothèque statique pour convertir enums en List<SelectListItem>
avec quelques paramètres / options:
public static List<SelectListItem> GetEnumsByType<T>(bool useFriendlyName = false, List<T> exclude = null,
List<T> eachSelected = null, bool useIntValue = true) where T : struct, IConvertible
{
var enumList = from enumItem in EnumUtil.GetEnumValuesFor<T>()
where (exclude == null || !exclude.Contains(enumItem))
select enumItem;
var list = new List<SelectListItem>();
foreach (var item in enumList)
{
var selItem = new SelectListItem();
selItem.Text = (useFriendlyName) ? item.ToFriendlyString() : item.ToString();
selItem.Value = (useIntValue) ? item.To<int>().ToString() : item.ToString();
if (eachSelected != null && eachSelected.Contains(item))
selItem.Selected = true;
list.Add(selItem);
}
return list;
}
public static class EnumUtil
{
public static IEnumerable<T> GetEnumValuesFor<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
// other stuff in here too...
}
/// <summary>
/// Turns Camelcase or underscore separated phrases into properly spaces phrases
/// "DogWithMustard".ToFriendlyString() == "Dog With Mustard"
/// </summary>
public static string ToFriendlyString(this object o)
{
var s = o.ToString();
s = s.Replace("__", " / ").Replace("_", " ");
char[] origArray = s.ToCharArray();
List<char> newCharList = new List<char>();
for (int i = 0; i < origArray.Count(); i++)
{
if (origArray[i].ToString() == origArray[i].ToString().ToUpper())
{
newCharList.Add(' ');
}
newCharList.Add(origArray[i]);
}
s = new string(newCharList.ToArray()).TrimStart();
return s;
}
votre ViewModel peut passer dans les options que vous voulez. Voici une assez complexe:
public IEnumerable<SelectListItem> PaymentMethodChoices
{
get
{
var exclusions = new List<Membership.Payment.PaymentMethod> { Membership.Payment.PaymentMethod.Unknown, Membership.Payment.PaymentMethod.Reversal };
var selected = new List<Membership.Payment.PaymentMethod> { this.SelectedPaymentMethod };
return GetEnumsByType<Membership.Payment.PaymentMethod>(useFriendlyName: true, exclude: exclusions, eachSelected: selected);
}
}
votre vue DropDownList
contre cette propriété IEnumerable<SelectListItem>
.
étendre le helper html pour le faire fonctionne bien, mais si vous souhaitez être en mesure de changer le texte de la baisse des valeurs basées sur DisplayAttribute mappings, alors vous aurez besoin de le modifier similaire à cela,
(pré MVC 5.1, il est inclus dans l'5.1+)
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 = enumValues.Select(item =>
{
var type = item.GetType();
var member = type.GetMember(item.ToString());
var attribute = member[0].GetCustomAttribute<DisplayAttribute>();
string text = attribute != null ? ((DisplayAttribute)attribute).Name : item.ToString();
string value = ((int)item).ToString();
bool selected = item.Equals(metadata.Model);
return new SelectListItem
{
Text = text,
Value = value,
Selected = selected
};
});
return html.DropDownListFor(expression, items, string.Empty, null);
}