可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
How do you create a dropdownlist from an enum in ASP.NET MVC?
36 answers
I've been finding all over the place that the common way to bind Enums to DropDowns is through helper methods, which seems a bit overbearing for such a seemingly simple task.
What is the best way to bind Enums to DropDownLists in ASP.Net MVC 4?
回答1:
I think it is about the only (clean) way, which is a pity, but at least there are a few options out there. I'd recommend having a look at this blog: http://paulthecyclist.com/2013/05/24/enum-dropdown/
Sorry, it's too long to copy here, but the gist is that he created a new HTML helper method for this.
All the source code is available on GitHub.
回答2:
You can to this:
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
回答3:
Enums are supported by the framework since MVC 5.1:
@Html.EnumDropDownListFor(m => m.Palette)
Displayed text can be customized:
public enum Palette
{
[Display(Name = "Black & White")]
BlackAndWhite,
Colour
}
MSDN link: http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum
回答4:
In my Controller:
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);
In my View:
@Html.DropDownList("FeedType", (SelectList)ViewBag.FeedTypeList)
回答5:
The solution from PaulTheCyclist is spot on. But I wouldn't use RESX (I'd have to add a new .resx file for each new enum??)
Here is my HtmlHelper Expression:
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);
}
Here is how I declare my enums:
[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,
}
And here is the call from a Razor View:
<div class="control-group span2">
<div class="controls">
@Html.EnumDropDownListFor(m => m.LoanType, new { @class = "span2" })
</div>
</div>
Where @Model.LoanType
is an model property of the LoanApplicationType type
UPDATE: Sorry, forgot to include code for the helper function 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);
}
回答6:
Technically, you don't need a helper method, since Html.DropdownListFor
only requires a SelectList
or Ienumerable<SelectListItem>
. You can just turn your enums into such an output and feed it in that way.
I use a static library method to convert enums into List<SelectListItem>
with a few params/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;
}
Your ViewModel can pass in the options you want. Here's a fairly complex one:
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);
}
}
So you wire your View's DropDownList
against that IEnumerable<SelectListItem>
property.
回答7:
Extending the html helper to do it works well, but if you'd like to be able to change the text of the drop down values based on DisplayAttribute mappings, then you would need to modify it similar to this,
(Do this pre MVC 5.1, it's included in 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);
}