I have an enum for one of the properties of my view-model. I want to display a drop-down list that contains all the values of the enum. I can get this to work with the following code.
我有一个枚举我的视图模型的属性之一。我想显示一个下拉列表,其中包含枚举的所有值。我可以使用以下代码使用它。
What I'm wondering is whether there is a simple way to convert from an enum to an IEnumerable? I can do it manually as in the following example, but when I add a new enum value the code breaks. I imagine that I can do it via reflection as per this example, but but are there other ways to do this?
我想知道是否有一种简单的方法从枚举转换为IEnumerable?我可以手动执行,如下例所示,但是当我添加新的枚举值时,代码会中断。我想我可以通过反射按照这个例子来做,但是还有其他方法吗?
public enum Currencies
{
CAD, USD, EUR
}
public ViewModel
{
[Required]
public Currencies SelectedCurrency {get; set;}
public SelectList Currencies
{
List<Currencies> c = new List<Currencies>();
c.Add(Currencies.CAD);
c.Add(Currencies.USD);
c.Add(Currencies.EUR);
return new SelectList(c);
}
}
5 个解决方案
#1
18
I'm using a helper that i found here to populate my SelectLists with a generic enum type, i did a little modification to add the selected value though, here's how it looks like :
我正在使用一个帮助器,我在这里用一个通用的枚举类型填充我的SelectLists,我做了一些修改来添加所选的值,但这是它的样子:
public static SelectList ToSelectList<T>(this T enumeration, string selected)
{
var source = Enum.GetValues(typeof(T));
var items = new Dictionary<object, string>();
var displayAttributeType = typeof(DisplayAttribute);
foreach (var value in source)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DisplayAttribute attrs = (DisplayAttribute)field.
GetCustomAttributes(displayAttributeType, false).FirstOrDefault()
items.Add(value, attrs != null ? attrs.GetName() : value.ToString());
}
return new SelectList(items, "Key", "Value", selected);
}
The nice thing about it is that it reads the DisplayAttribute as the title rather than the enum name. (if your enums contain spaces or you need localization then it makes your life much easier)
关于它的好处是它将DisplayAttribute读作标题而不是枚举名称。 (如果您的枚举包含空格或您需要本地化,那么它会让您的生活更轻松)
So you will need to add the Display attirubete to your enums like this :
因此,您需要将Display attirubete添加到您的枚举中,如下所示:
public enum User_Status
{
[Display(Name = "Waiting Activation")]
Pending, // User Account Is Pending. Can Login / Can't participate
[Display(Name = "Activated" )]
Active, // User Account Is Active. Can Logon
[Display(Name = "Disabled" )]
Disabled, // User Account Is Diabled. Can't Login
}
and this is how you use them in your views.
这就是你在视图中使用它们的方式。
<%: Html.DropDownList("ChangeStatus" , ListExtensions.ToSelectList(Model.statusType, user.Status))%>
Model.statusType
is just an enum object of type User_Status
.
Model.statusType只是User_Status类型的枚举对象。
That's it , no more SelectLists in your ViewModels. In my example I'm refrencing an enum in my ViewModel but you can Refrence the enum type directly in your view though. I'm just doing it to make everything clean and nice.
就是这样,ViewModel中不再有SelectLists。在我的例子中,我正在我的ViewModel中重新生成一个枚举,但你可以直接在你的视图中引用枚举类型。我只是这样做,让一切都干净漂亮。
Hope that was helpful.
希望这很有帮助。
#2
2
Look at Enum.GetNames(typeof(Currencies))
看看Enum.GetNames(typeof(Currencies))
#3
1
So many good answers - I thought I'sd add my solution - I am building the SelectList in the view (and not in the Controller):
这么多好的答案 - 我以为我要添加我的解决方案 - 我在视图中构建SelectList(而不是在Controller中):
In my c#:
在我的c#中:
namespace ControlChart.Models
//My Enum
public enum FilterType {
[Display(Name = "Reportable")]
Reportable = 0,
[Display(Name = "Non-Reportable")]
NonReportable,
[Display(Name = "All")]
All };
//My model:
public class ChartModel {
[DisplayName("Filter")]
public FilterType Filter { get; set; }
}
In my cshtml:
在我的cshtml中:
@using System.ComponentModel.DataAnnotations
@using ControlChart.Models
@model ChartMode
@*..........*@
@Html.DropDownListFor(x => x.Filter,
from v in (ControlChart.Models.FilterType[])(Enum.GetValues(typeof(ControlChart.Models.FilterType)))
select new SelectListItem() {
Text = ((DisplayAttribute)(typeof(FilterType).GetField(v.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false).First())).Name,
Value = v.ToString(),
Selected = v == Model.Filter
})
HTH
HTH
#4
1
I am very late on this one but I just found a really cool way to do this with one line of code, if you are happy to add the Unconstrained Melody NuGet package (a nice, small library from Jon Skeet).
我在这个问题上已经很晚了,但是如果您乐意添加Unconstrained Melody NuGet软件包(来自Jon Skeet的一个漂亮的小型库),我只想用一行代码找到一个非常酷的方法。
This solution is better because:
此解决方案更好,因为:
- It ensures (with generic type constraints) that the value really is an enum value (due to Unconstrained Melody)
- 它确保(使用泛型类型约束)该值实际上是枚举值(由于Unconstrained Melody)
- It avoids unnecessary boxing (due to Unconstrained Melody)
- 它避免了不必要的拳击(由于无约束的旋律)
- It caches all the descriptions to avoid using reflection on every call (due to Unconstrained Melody)
- 它会缓存所有描述以避免在每次调用时使用反射(由于Unconstrained Melody)
- It is less code than the other solutions!
- 它的代码少于其他解决方案!
So, here are the steps to get this working:
所以,这是让这个工作的步骤:
- In Package Manager Console, "Install-Package UnconstrainedMelody"
- 在软件包管理器控制台中,“Install-Package UnconstrainedMelody”
-
Add a property on your model like so:
在模型上添加属性,如下所示:
//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() }); } }
Now that you have the List of SelectListItem exposed on your model, you can use the @Html.DropDownList or @Html.DropDownListFor using this property as the source.
现在您已在模型上公开了ListListItem,您可以使用@ Html.DropDownList或@ Html.DropDownListFor将此属性用作源。
#5
1
Maybe is too late, but i think it could be useful for people with the same problem. I've found here that now with MVC 5 it's included an EnumDropDownListFor html helper that makes for no longer necesary the use of custom helpers or other workarounds.
也许为时已晚,但我认为它可能对有同样问题的人有用。我在这里发现,现在使用MVC 5,它包含了一个EnumDropDownListFor html帮助程序,不再需要使用自定义帮助程序或其他解决方法。
In this particular case, just add this:
在这种特殊情况下,只需添加:
@Html.EnumDropDownListFor(x => x.SelectedCurrency)
and that's all!
就这样!
You can also translate or change the displayed text via data annotations and resources files:
您还可以通过数据注释和资源文件翻译或更改显示的文本:
-
Add the following data annotations to your enum:
将以下数据注释添加到枚举中:
public enum Currencies { [Display(Name="Currencies_CAD", ResourceType=typeof(Resources.Enums)] CAD, [Display(Name="Currencies_USD", ResourceType=typeof(Resources.Enums)] USD, [Display(Name="Currencies_EUR", ResourceType=typeof(Resources.Enums)] EUR }
-
Create the corresponding resources file.
创建相应的资源文件。
#1
18
I'm using a helper that i found here to populate my SelectLists with a generic enum type, i did a little modification to add the selected value though, here's how it looks like :
我正在使用一个帮助器,我在这里用一个通用的枚举类型填充我的SelectLists,我做了一些修改来添加所选的值,但这是它的样子:
public static SelectList ToSelectList<T>(this T enumeration, string selected)
{
var source = Enum.GetValues(typeof(T));
var items = new Dictionary<object, string>();
var displayAttributeType = typeof(DisplayAttribute);
foreach (var value in source)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DisplayAttribute attrs = (DisplayAttribute)field.
GetCustomAttributes(displayAttributeType, false).FirstOrDefault()
items.Add(value, attrs != null ? attrs.GetName() : value.ToString());
}
return new SelectList(items, "Key", "Value", selected);
}
The nice thing about it is that it reads the DisplayAttribute as the title rather than the enum name. (if your enums contain spaces or you need localization then it makes your life much easier)
关于它的好处是它将DisplayAttribute读作标题而不是枚举名称。 (如果您的枚举包含空格或您需要本地化,那么它会让您的生活更轻松)
So you will need to add the Display attirubete to your enums like this :
因此,您需要将Display attirubete添加到您的枚举中,如下所示:
public enum User_Status
{
[Display(Name = "Waiting Activation")]
Pending, // User Account Is Pending. Can Login / Can't participate
[Display(Name = "Activated" )]
Active, // User Account Is Active. Can Logon
[Display(Name = "Disabled" )]
Disabled, // User Account Is Diabled. Can't Login
}
and this is how you use them in your views.
这就是你在视图中使用它们的方式。
<%: Html.DropDownList("ChangeStatus" , ListExtensions.ToSelectList(Model.statusType, user.Status))%>
Model.statusType
is just an enum object of type User_Status
.
Model.statusType只是User_Status类型的枚举对象。
That's it , no more SelectLists in your ViewModels. In my example I'm refrencing an enum in my ViewModel but you can Refrence the enum type directly in your view though. I'm just doing it to make everything clean and nice.
就是这样,ViewModel中不再有SelectLists。在我的例子中,我正在我的ViewModel中重新生成一个枚举,但你可以直接在你的视图中引用枚举类型。我只是这样做,让一切都干净漂亮。
Hope that was helpful.
希望这很有帮助。
#2
2
Look at Enum.GetNames(typeof(Currencies))
看看Enum.GetNames(typeof(Currencies))
#3
1
So many good answers - I thought I'sd add my solution - I am building the SelectList in the view (and not in the Controller):
这么多好的答案 - 我以为我要添加我的解决方案 - 我在视图中构建SelectList(而不是在Controller中):
In my c#:
在我的c#中:
namespace ControlChart.Models
//My Enum
public enum FilterType {
[Display(Name = "Reportable")]
Reportable = 0,
[Display(Name = "Non-Reportable")]
NonReportable,
[Display(Name = "All")]
All };
//My model:
public class ChartModel {
[DisplayName("Filter")]
public FilterType Filter { get; set; }
}
In my cshtml:
在我的cshtml中:
@using System.ComponentModel.DataAnnotations
@using ControlChart.Models
@model ChartMode
@*..........*@
@Html.DropDownListFor(x => x.Filter,
from v in (ControlChart.Models.FilterType[])(Enum.GetValues(typeof(ControlChart.Models.FilterType)))
select new SelectListItem() {
Text = ((DisplayAttribute)(typeof(FilterType).GetField(v.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false).First())).Name,
Value = v.ToString(),
Selected = v == Model.Filter
})
HTH
HTH
#4
1
I am very late on this one but I just found a really cool way to do this with one line of code, if you are happy to add the Unconstrained Melody NuGet package (a nice, small library from Jon Skeet).
我在这个问题上已经很晚了,但是如果您乐意添加Unconstrained Melody NuGet软件包(来自Jon Skeet的一个漂亮的小型库),我只想用一行代码找到一个非常酷的方法。
This solution is better because:
此解决方案更好,因为:
- It ensures (with generic type constraints) that the value really is an enum value (due to Unconstrained Melody)
- 它确保(使用泛型类型约束)该值实际上是枚举值(由于Unconstrained Melody)
- It avoids unnecessary boxing (due to Unconstrained Melody)
- 它避免了不必要的拳击(由于无约束的旋律)
- It caches all the descriptions to avoid using reflection on every call (due to Unconstrained Melody)
- 它会缓存所有描述以避免在每次调用时使用反射(由于Unconstrained Melody)
- It is less code than the other solutions!
- 它的代码少于其他解决方案!
So, here are the steps to get this working:
所以,这是让这个工作的步骤:
- In Package Manager Console, "Install-Package UnconstrainedMelody"
- 在软件包管理器控制台中,“Install-Package UnconstrainedMelody”
-
Add a property on your model like so:
在模型上添加属性,如下所示:
//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() }); } }
Now that you have the List of SelectListItem exposed on your model, you can use the @Html.DropDownList or @Html.DropDownListFor using this property as the source.
现在您已在模型上公开了ListListItem,您可以使用@ Html.DropDownList或@ Html.DropDownListFor将此属性用作源。
#5
1
Maybe is too late, but i think it could be useful for people with the same problem. I've found here that now with MVC 5 it's included an EnumDropDownListFor html helper that makes for no longer necesary the use of custom helpers or other workarounds.
也许为时已晚,但我认为它可能对有同样问题的人有用。我在这里发现,现在使用MVC 5,它包含了一个EnumDropDownListFor html帮助程序,不再需要使用自定义帮助程序或其他解决方法。
In this particular case, just add this:
在这种特殊情况下,只需添加:
@Html.EnumDropDownListFor(x => x.SelectedCurrency)
and that's all!
就这样!
You can also translate or change the displayed text via data annotations and resources files:
您还可以通过数据注释和资源文件翻译或更改显示的文本:
-
Add the following data annotations to your enum:
将以下数据注释添加到枚举中:
public enum Currencies { [Display(Name="Currencies_CAD", ResourceType=typeof(Resources.Enums)] CAD, [Display(Name="Currencies_USD", ResourceType=typeof(Resources.Enums)] USD, [Display(Name="Currencies_EUR", ResourceType=typeof(Resources.Enums)] EUR }
-
Create the corresponding resources file.
创建相应的资源文件。