Html 将枚举绑定到 MVC 4 中的 DropDownList?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17280906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binding an Enum to a DropDownList in MVC 4?
提问by Kehlan Krumme
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.
我到处都发现将 Enums 绑定到 DropDowns 的常用方法是通过辅助方法,对于这样一个看似简单的任务来说,这似乎有点霸道。
What is the best way to bind Enums to DropDownLists in ASP.Net MVC 4?
在 ASP.Net MVC 4 中将 Enums 绑定到 DropDownLists 的最佳方法是什么?
回答by Mr. Pumpkin
You can to this:
你可以这样做:
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
回答by Bernhard Hofmann
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/
我认为这是唯一的(干净的)方式,很遗憾,但至少有一些选择。我建议看看这个博客: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.
抱歉,复制到这里太长了,但要点是他为此创建了一个新的 HTML 辅助方法。
All the source code is available on GitHub.
回答by Mihkel Müür
Enums are supported by the framework since MVC 5.1:
自 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
MSDN 链接:http: //www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum
回答by Kehlan Krumme
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)
回答by amhed
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??)
PaulTheCyclist 的解决方案是正确的。但我不会使用 RESX(我必须为每个新枚举添加一个新的 .resx 文件??)
Here is my HtmlHelper 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);
}
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:
这是来自 Razor 视图的调用:
<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
@Model.LoanType
LoanApplicationType 类型的模型属性在哪里
UPDATE:Sorry, forgot to include code for the helper function ToDescription()
更新:抱歉,忘记包含辅助函数 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);
}
回答by Graham
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.
从技术上讲,您不需要辅助方法,因为Html.DropdownListFor
只需要一个SelectList
or Ienumerable<SelectListItem>
。您可以将枚举转换为这样的输出并以这种方式提供它。
I use a static library method to convert enums into List<SelectListItem>
with a few params/options:
我使用静态库方法将枚举转换List<SelectListItem>
为一些参数/选项:
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:
您的 ViewModel 可以传入您想要的选项。这是一个相当复杂的:
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.
因此,您将视图DropDownList
与该IEnumerable<SelectListItem>
属性连接起来。
回答by Ryan Mann
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,
扩展 html helper 可以很好地完成它,但是如果您希望能够根据 DisplayAttribute 映射更改下拉值的文本,那么您需要像这样修改它,
(Do this pre MVC 5.1, it's included in 5.1+)
(在 MVC 5.1 之前执行此操作,它包含在 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);
}