2012-02-17 9 views
23

mam następujące metody pomocnika w ViewModelBase klasy, która dziedziczy Zobacz inne modele:MVC.net get enum nazwa wyświetlana w widoku bez konieczności odwoływania się do typu enum w świetle

public string GetEnumName<T>(Enum value) 
     { 
      Type enumType = typeof(T); 
      var enumValue = Enum.GetName(enumType, value); 
      MemberInfo member = enumType.GetMember(enumValue)[0]; 

      var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false); 
      var outString = ((DisplayAttribute)attrs[0]).Name; 

      if (((DisplayAttribute)attrs[0]).ResourceType != null) 
      { 
       outString = ((DisplayAttribute)attrs[0]).GetName(); 
      } 

      return outString; 
     } 

I następnie zadzwonić to z punktu widzenia jak to:

<p> 
@{var rel = Model.GetEnumDisplayName<Enums.wheteverEnum>(Model.wheteverEnum); } 
@rel 
</p> 

Pytanie brzmi - czy mogę pracować z tej metody, więc nie muszę powiedzieć, że ten typ enum? Zasadniczo chciałbym todo to dla wszystkich enum s:

@ Model.GetEnumDisplayName (Model.wheteverEnum)

Nie typeof, nie T, nie ma potrzeby, aby dodać odwołanie do przestrzeni nazw Enums w Widoku ...

Możliwe?

Odpowiedz

54

można po prostu usunąć parametr typu i sprawiają, że jest to metoda rozszerzenie.

public static string DisplayName(this Enum value) 
    { 
     Type enumType = value.GetType(); 
     var enumValue = Enum.GetName(enumType, value); 
     MemberInfo member = enumType.GetMember(enumValue)[0]; 

     var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false); 
     var outString = ((DisplayAttribute)attrs[0]).Name; 

     if (((DisplayAttribute)attrs[0]).ResourceType != null) 
     { 
      outString = ((DisplayAttribute)attrs[0]).GetName(); 
     } 

     return outString; 
    } 

    @Model.wheteverEnum.DisplayName() 
+0

+1 Bardzo ładne. Jest używany oryginalny kod Plus dodaje realizację kodu metody wydłużania łącznie jak to nazwać. – Nope

+2

Dla c sompleteness sake, powinieneś dodać sprawdzenie, czy istnieją jakieś 'DisplayAttributes' zastosowane do wartości wyliczeniowej i zwrócić' value.ToString() 'jako domyślną, jeśli nie ma żadnych. W przeciwnym razie otrzymasz 'IndexOutOfRangeException' po wywołaniu' ((DisplayAttribute) attrs [0]). Name ' – flipchart

+0

Jeśli ktoś próbuje połączyć się ze sterownikiem: DisplayName (id (MyEnum) id); –

7

Nie możesz zapisać tego jako metody rozszerzenia? Coś jak ...

public static class EnumExtensions 
{ 
    public static string ToDescription(this Enum e) 
    { 
    var attributes = (DisplayAttribute[])e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false); 
    return attributes.Length > 0 ? attributes[0].Description : string.Empty; 
    } 
} 

Zastosowanie:

@Model.WhateverEnum.ToDescription(); 
0

Oto metoda rozszerzenie, które pisałem właśnie do tego ... ma trochę więcej logiki w tym do analizowania nazw ENUM i podzielić przez literami. Można zastąpić dowolną nazwę przy użyciu atrybutu Wyświetlacz

public static TAttribute GetAttribute<TAttribute>(this ICustomAttributeProvider parameterInfo) where TAttribute : Attribute 
{ 
    object[] attributes = parameterInfo.GetCustomAttributes(typeof(TAttribute), false); 
    return attributes.Length > 0 ? (TAttribute)attributes[0] : null; 
} 
public static bool HasAttribute<TAttribute>(this ICustomAttributeProvider parameterInfo) where TAttribute : Attribute 
{ 
    object[] attributes = parameterInfo.GetCustomAttributes(typeof(TAttribute), false); 
    return attributes.Length > 0 ? true : false; 
} 

public static string ToFriendlyEnum(this Enum type) 
{ 
    return type.GetType().HasAttribute<DescriptionAttribute>() ? type.GetType().GetAttribute<DescriptionAttribute>().Description : type.ToString().ToFriendlyEnum(); 
} 

public static string ToFriendlyEnum(this string value) 
{ 
    char[] chars = value.ToCharArray(); 
    string output = string.Empty; 

    for (int i = 0; i < chars.Length; i++) 
    { 
     if (i <= 0 || chars[i - 1].ToString() != chars[i - 1].ToString().ToUpper() && chars[i].ToString() != chars[i].ToString().ToLower()) 
     { 
      output += " "; 
     } 

     output += chars[i]; 
    } 

    return output.Trim(); 
} 

Metody przedłużających getAttribute mógłby być nieco przesada, ale używam je w innym miejscu w moich projektach, więc dostali ponownie wykorzystane, gdy pisałam rozszerzenie Enum. Możesz łatwo połączyć je z powrotem w ToFriendlyEnum (ta metoda typu Enum)

5

Dobra robota @jrummell!

Dodałem mały uszczypnąć poniżej której oddaje scenariusz gdzie enum nie ma skojarzonego Wyświetlacz atrybut (obecnie zgłasza wyjątek)

/// <summary> 
/// Gets the DataAnnotation DisplayName attribute for a given enum (for displaying enums values nicely to users) 
/// </summary> 
/// <param name="value">Enum value to get display for</param> 
/// <returns>Pretty version of enum (if there is one)</returns> 
/// <remarks> 
/// Inspired by : 
///  http://stackoverflow.com/questions/9328972/mvc-net-get-enum-display-name-in-view-without-having-to-refer-to-enum-type-in-vi 
/// </remarks> 
public static string DisplayFor(this Enum value) { 
    Type enumType = value.GetType(); 
    var enumValue = Enum.GetName(enumType, value); 
    MemberInfo member = enumType.GetMember(enumValue)[0]; 
    string outString = ""; 

    var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false); 
    if (attrs.Any()) { 
     var displayAttr = ((DisplayAttribute)attrs[0]); 

     outString = displayAttr.Name; 

     if (displayAttr.ResourceType != null) { 
      outString = displayAttr.GetName(); 
     } 
    } else { 
     outString = value.ToString(); 
    } 

    return outString; 
} 
0

Proponowane sollutions nie pracował dla mi z MVC3: więc poniżej pomocnik jest dobra .:

public static string GetEnumDescription(this Enum value) 
    { 
     Type type = value.GetType(); 
     string name = Enum.GetName(type, value); 
     if (name != null) 
     { 
      FieldInfo field = type.GetField(name); 
      if (field != null) 
      { 
       string attr = field.GetCustomAttributesData()[0].NamedArguments[0].TypedValue.Value.ToString(); 
       if (attr == null) 
       { 
        return name; 
       } 
       else 
       { 
        return attr; 
       } 
      } 
     } 
     return null; 
    } 
1

odpowiedź @jrummell w VB.NET dla niewielu z nas ...

Module ModuleExtension 

    <Extension()> 
    Public Function DisplayName(ByVal value As System.Enum) As String 

     Dim enumType As Type = value.GetType() 
     Dim enumValue = System.Enum.GetName(enumType, value) 
     Dim member As MemberInfo = enumType.GetMember(enumValue)(0) 

     Dim attrs = member.GetCustomAttributes(GetType(DisplayAttribute), False) 
     Dim outString = CType(attrs(0), DisplayAttribute).Name 

     If (CType(attrs(0), DisplayAttribute).ResourceType IsNot Nothing) Then 
      outString = CType(attrs(0), DisplayAttribute).GetName() 
     End If 

     Return outString 
    End Function 


End Module 
1

dla każdego, kto może dojść do tego pytania, znalazłem to o wiele łatwiejsze niż czymkolwiek innym: https://www.codeproject.com/articles/776908/dealing-with-enum-in-mvc

wystarczy utworzyć folder „DisplayTemplate” pod „Widoki \ Shared” i utworzyć pusty widok (nazwa to „Enum”) w nowym folderze „DisplayTemplate”, a następnie skopiować ten kod do niego”

@model Enum 

@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata)) 
{ 
    // Display Enum using same names (from [Display] attributes) as in editors 
    string displayName = null; 
    foreach (SelectListItem item in EnumHelper.GetSelectList(ViewData.ModelMetadata, (Enum)Model)) 
    { 
     if (item.Selected) 
     { 
      displayName = item.Text ?? item.Value; 
     } 
    } 

    // Handle the unexpected case that nothing is selected 
    if (String.IsNullOrEmpty(displayName)) 
    { 
     if (Model == null) 
     { 
      displayName = String.Empty; 
     } 
     else 
     { 
      displayName = Model.ToString(); 
     } 
    } 

    @Html.DisplayTextFor(model => displayName) 
} 
else 
{ 
    // This Enum type is not supported. Fall back to the text. 
    @Html.DisplayTextFor(model => model) 
}