如何通过MVC剃刀代码获取Enum成员的显示名称属性?

Pej*_*man 185 c# asp.net-mvc displayattribute razor

我的模型中有一个名为"Promotion"的属性,它的类型是一个名为"UserPromotion"的标志枚举.我的枚举成员的显示属性设置如下:

[Flags]
public enum UserPromotion
{
    None = 0x0,

    [Display(Name = "Send Job Offers By Mail")]
    SendJobOffersByMail = 0x1,

    [Display(Name = "Send Job Offers By Sms")]
    SendJobOffersBySms = 0x2,

    [Display(Name = "Send Other Stuff By Sms")]
    SendPromotionalBySms = 0x4,

    [Display(Name = "Send Other Stuff By Mail")]
    SendPromotionalByMail = 0x8
}
Run Code Online (Sandbox Code Playgroud)

现在我希望能够在我的视图中创建一个ul来显示我的"Promotion"属性的选定值.这是我到目前为止所做的,但问题是如何在这里获取显示名称?

<ul>
    @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
    {
        var currentPromotion = (int)Model.JobSeeker.Promotion;
        if ((currentPromotion & aPromotion) == aPromotion)
        {
        <li>Here I don't know how to get the display attribute of "currentPromotion".</li>
        }
    }
</ul>
Run Code Online (Sandbox Code Playgroud)

小智 166

UPDATE

第一个解决方案专注于从枚举中获取显示名称.以下代码应该是您问题的准确解决方案.

您可以将此辅助类用于枚举:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumHelper<T>
{
    public static IList<T> GetValues(Enum value)
    {
        var enumValues = new List<T>();

        foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
        {
            enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
        }
        return enumValues;
    }

    public static T Parse(string value)
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }

    public static IList<string> GetNames(Enum value)
    {
        return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
    }

    public static IList<string> GetDisplayValues(Enum value)
    {
        return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
    }

    private static string lookupResource(Type resourceManagerProvider, string resourceKey)
    {
        foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
        {
            if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
            {
                System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
                return resourceManager.GetString(resourceKey);
            }
        }

        return resourceKey; // Fallback with the key name
    }

    public static string GetDisplayValue(T value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());

        var descriptionAttributes = fieldInfo.GetCustomAttributes(
            typeof(DisplayAttribute), false) as DisplayAttribute[];

        if (descriptionAttributes[0].ResourceType != null)
            return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);

        if (descriptionAttributes == null) return string.Empty;
        return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以在视图中使用它,如下所示:

<ul>
    @foreach (var value in @EnumHelper<UserPromotion>.GetValues(UserPromotion.None))
    {
         if (value == Model.JobSeeker.Promotion)
        {
            var description = EnumHelper<UserPromotion>.GetDisplayValue(value);
            <li>@Html.DisplayFor(e => description )</li>
        }
    }
</ul>
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!:)

  • 所有的答案都使用`.ToString`,但是从http://stackoverflow.com/q/483794/179311,它说使用'Enum.GetName`代替. (8认同)
  • 在`GetDisplayValue`中,在尝试访问数组之前,首先应该测试`descriptionAttributes == null`:`descriptionAttributes [0]`.否则,您可能会引发异常,并且您检查null的下面的行将永远不会成立. (4认同)

Ayd*_*din 148

一个班轮 - 流利的语法

public static class Extensions
{
    /// <summary>
    ///     A generic extension method that aids in reflecting 
    ///     and retrieving any attribute that is applied to an `Enum`.
    /// </summary>
    public static TAttribute GetAttribute<TAttribute>(this Enum enumValue) 
            where TAttribute : Attribute
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<TAttribute>();
    }
}
Run Code Online (Sandbox Code Playgroud)

public enum Season 
{
   [Display(Name = "It's autumn")]
   Autumn,

   [Display(Name = "It's winter")]
   Winter,

   [Display(Name = "It's spring")]
   Spring,

   [Display(Name = "It's summer")]
   Summer
}

public class Foo 
{
    public Season Season = Season.Summer;

    public void DisplayName()
    {
        var seasonDisplayName = Season.GetAttribute<DisplayAttribute>();
        Console.WriteLine("Which season is it?");
        Console.WriteLine (seasonDisplayName.Name);
    } 
}
Run Code Online (Sandbox Code Playgroud)

产量

哪个季节?
夏天到了

  • 使用System.Reflection; 使用System.ComponentModel.DataAnnotations; 对我来说是必要的. (5认同)
  • @Tito确保您的项目瞄准`.NET Framework 4.5`并且您包含以下名称空间`System.Net``System.ComponentModel.DataAnnotations` (3认同)
  • 不存在GetCustomAttribute的定义 (2认同)

Tod*_*odd 121

基于Aydin的优秀答案,这是一个不需要任何类型参数的扩展方法.

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum enumValue)
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<DisplayAttribute>()
                        .GetName();
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:应使用GetName()而不是Name属性.这可确保在使用ResourceType属性属性时将返回本地化字符串.

要使用它,只需在视图中引用枚举值即可.

@{
    UserPromotion promo = UserPromotion.SendJobOffersByMail;
}

Promotion: @promo.GetDisplayName()
Run Code Online (Sandbox Code Playgroud)

产量

促销:通过邮件发送工作机会

  • 我在`GetCustomAttribute <DisplayAttribute>()`的结果中添加了一个空引用检查,因为对于某些枚举,这可能不存在.如果DisplayAttribute不存在,它会回退到`enumValue.ToString()`. (5认同)
  • 确保添加以下命名空间:using System; 使用System.ComponentModel.DataAnnotations; 使用System.Linq; 使用System.Reflection; (4认同)
  • 我用它来创建一个 `List&lt;SelectListItem&gt;`,它由一个带有所有单独的 `DisplayAttribute.Name` 注释的 Enum 填充 - 这工作得很好,谢谢!`public List&lt;SelectListItem&gt; MySelectListItem = new List&lt;SelectListItem&gt;(); foreach (MyEnum MyEnum in Enum.GetValues(typeof(MyEnum)).Cast&lt;MyEnum&gt;().Where(x =&gt; x != MyEnum.Default)) { MySelectListItem.Add(new SelectListItem() { Text = MyEnum.GetDisplayName (), Value = ((int)MyEnum).ToString() }); }` (2认同)

Ber*_* IT 58

根据Aydin的回答,我建议一个不那么"重复"的实现(因为我们可以轻松地TypeEnum值本身获取,而不是将其作为参数提供:

public static string GetDisplayName(this Enum enumValue)
{
    return enumValue.GetType().GetMember(enumValue.ToString())
                   .First()
                   .GetCustomAttribute<DisplayAttribute>()
                   .Name;
}
Run Code Online (Sandbox Code Playgroud)

编辑(基于@Vahagn Nahapetyan的评论)

public static string GetDisplayName(this Enum enumValue)
{
    return enumValue.GetType()?
                    .GetMember(enumValue.ToString())?
                    .First()?
                    .GetCustomAttribute<DisplayAttribute>()?
                    .Name;
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以用这种方式非常干净地使用它:

public enum Season 
{
    [Display(Name = "The Autumn")]
    Autumn,

    [Display(Name = "The Weather")]
    Winter,

    [Display(Name = "The Tease")]
    Spring,

    [Display(Name = "The Dream")]
    Summer
}

Season.Summer.GetDisplayName();
Run Code Online (Sandbox Code Playgroud)

结果如何

"梦想"

  • 对于代码的第二个变体,似乎不需要在 GetMember 之后使用 null 条件运算符,因为此方法始终返回 MemberInfo 数组并且从不返回 null。对我来说,似乎最好使用 FirstOrDefault 而不是仅使用 First。那么在 FirstOrDefault 之后使用空条件运算符将是一致的。 (2认同)

1_b*_*bug 27

如果您使用的是MVC 5.1或更高版本,则可以使用更简单,更清晰的方法:只需使用数据注释(来自System.ComponentModel.DataAnnotations命名空间),如下所示:

public enum Color
{
    [Display(Name = "Dark red")]
    DarkRed,
    [Display(Name = "Very dark red")]
    VeryDarkRed,
    [Display(Name = "Red or just black?")]
    ReallyDarkRed
}
Run Code Online (Sandbox Code Playgroud)

并且在视图中,只需将其放入正确的html助手:

@Html.EnumDropDownListFor(model => model.Color)
Run Code Online (Sandbox Code Playgroud)

  • 因为它只适用于Dropdown,而不适用于其他任何地方. (5认同)
  • .net核心使用Html.GetEnumSelectList(typeof(YourEnum))@Lonefish (3认同)
  • 在.net核心中似乎不存在 (2认同)
  • 如果我们想使用@ Html.DisplayFor(yourEnumField),我们可以将Enum.cshtml放在DisplayTemplates目录中(在共享目录中).在这个文件中我们只需要放两行.第一个是:"@ model Enum"第二个是:"@ GetDisplayName(Model)." GetDisplayName方法需要与@Bernoulli IT answare一样 (2认同)

max*_*mpa 11

您可以使用Type.GetMember方法,然后使用反射获取属性信息:

// display attribute of "currentPromotion"

var type = typeof(UserPromotion);
var memberInfo = type.GetMember(currentPromotion.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false);
var description = ((DisplayAttribute)attributes[0]).Name;
Run Code Online (Sandbox Code Playgroud)

这里有一些类似的帖子:

获得Enum价值的属性

如何使MVC3 DisplayFor显示Enum的显示属性的值?


Sea*_*ean 10

对于 ASP.Net Core 3.0,这对我有用(归功于以前的回答者)。

我的枚举类:

using System;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

public class Enums
{
    public enum Duration
    { 
        [Display(Name = "1 Hour")]
        OneHour,
        [Display(Name = "1 Day")]
        OneDay
    }

    // Helper method to display the name of the enum values.
    public static string GetDisplayName(Enum value)
    {
        return value.GetType()?
       .GetMember(value.ToString())?.First()?
       .GetCustomAttribute<DisplayAttribute>()?
       .Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的视图模型类:

public class MyViewModel
{
    public Duration Duration { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

显示标签和下拉列表的 razor 视图示例。注意下拉列表不需要辅助方法:

@model IEnumerable<MyViewModel> 

@foreach (var item in Model)
{
    <label asp-for="@item.Duration">@Enums.GetDisplayName(item.Duration)</label>
    <div class="form-group">
        <label asp-for="@item.Duration" class="control-label">Select Duration</label>
        <select asp-for="@item.Duration" class="form-control"
            asp-items="Html.GetEnumSelectList<Enums.Duration>()">
        </select>
    </div>
}
Run Code Online (Sandbox Code Playgroud)


Dmy*_*tro 6

<ul>
    @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
    {
        var currentPromotion = (int)Model.JobSeeker.Promotion;
        if ((currentPromotion & aPromotion) == aPromotion)
        {
        <li>@Html.DisplayFor(e => currentPromotion)</li>
        }
    }
</ul>
Run Code Online (Sandbox Code Playgroud)


Sin*_*jai 6

基于ToddAydin的优秀答案基础上的出色答案,这里是一个不需要任何类型参数的通用扩展方法.

/// <summary>
/// Gets human-readable version of enum.
/// </summary>
/// <returns>DisplayAttribute.Name property of given enum.</returns>
public static string GetDisplayName<T>(this T enumValue) where T : IComparable, IFormattable, IConvertible
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Argument must be of type Enum");

    DisplayAttribute displayAttribute = enumValue.GetType()
                                                 .GetMember(enumValue.ToString())
                                                 .First()
                                                 .GetCustomAttribute<DisplayAttribute>();

    string displayName = displayAttribute?.GetName();

    return displayName ?? enumValue.ToString();
}
Run Code Online (Sandbox Code Playgroud)

我需要这个用于我的项目,因为类似下面的代码,而不是枚举的每个成员都有DisplayAttribute,不适用于Todd的解决方案:

public class MyClass
{
    public enum MyEnum 
    {
        [Display(Name="ONE")]
        One,
        // No DisplayAttribute
        Two
    }
    public void UseMyEnum()
    {
        MyEnum foo = MyEnum.One;
        MyEnum bar = MyEnum.Two;
        Console.WriteLine(foo.GetDisplayName());
        Console.WriteLine(bar.GetDisplayName());
    }
}
// Output:
//
// ONE
// Two
Run Code Online (Sandbox Code Playgroud)

如果这是一个简单问题的复杂解决方案,请告诉我,但这是我使用的修复.


小智 6

使用 Core 2.1,

public static string GetDisplayName(Enum enumValue)
{
  return enumValue.GetType()?
 .GetMember(enumValue.ToString())?[0]?
 .GetCustomAttribute<DisplayAttribute>()?
 .Name;
}
Run Code Online (Sandbox Code Playgroud)


avs*_*099 5

从上面将所有边缘情况组合在一起:

  • 具有基对象成员名称 ( Equals, ToString) 的枚举成员
  • 可选Display属性

这是我的代码:

public enum Enum
{
    [Display(Name = "What a weird name!")]
    ToString,

    Equals
}

public static class EnumHelpers
{
    public static string GetDisplayName(this Enum enumValue)
    {
        var enumType = enumValue.GetType();

        return enumType
                .GetMember(enumValue.ToString())
                .Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == enumType)
                .First()
                .GetCustomAttribute<DisplayAttribute>()?.Name ?? enumValue.ToString();
    }
}

void Main()
{
    Assert.Equals("What a weird name!", Enum.ToString.GetDisplayName());
    Assert.Equals("Equals", Enum.Equals.GetDisplayName());
}
Run Code Online (Sandbox Code Playgroud)


tje*_*ans 5

在 .NET5 中,我使用DisplayTextFor而不需要帮助程序或扩展方法:

@Html.DisplayTextFor(m => m.SomeEnumProperty)
Run Code Online (Sandbox Code Playgroud)

其中SomeEnumProperty的值为:

public enum MyEnum
{
    [Display(Name = "Not started")]
    NotStarted = 0,
    [Display(Name = "Weird display name instead of just 'Started'")]
    Started = 1,
}
Run Code Online (Sandbox Code Playgroud)