2015-05-26 16 views
5

Ich habe dieses Enum (Notebook.cs):über Enum und DataAnnotation

public enum Notebook : byte 
{ 
    [Display(Name = "Notebook HP")] 
    NotebookHP, 

    [Display(Name = "Notebook Dell")] 
    NotebookDell 
} 

Auch diese Eigenschaft in meiner Klasse (TIDepartment.cs):

public Notebook Notebook { get; set; } 

Es ist perfekt funktioniert, ich habe nur ein "Problem":

Ich habe ein EnumDDLFor erstellt und es zeigt den Namen, den ich in DisplayAttribute eingestellt habe, mit Leerzeichen, aber das Objekt empfängt diesen Namen nicht in DisplayAttribute, empfängt den Enum-Namen (was ist richtig), also mein Frage ist:

Gibt es eine Möglichkeit, den Namen mit Leerzeichen zu erhalten, die ich in DisplayAttribute konfiguriert?

+0

Wie verwenden Sie die Enums für die Notebook-Eigenschaft? Dein Code ist etwas verwirrend. –

+0

Ich bearbeitet, können Sie jetzt schauen? – developer033

Antwort

3

MVC nicht die Verwendung des Display-Attribut auf Aufzählungen machen (oder einem Rahmen, den ich bin mir dessen bewusst). Sie müssen eine benutzerdefinierte Enum Erweiterungsklasse erstellen:

public static class EnumExtensions 
{ 
    public static string GetDisplayAttributeFrom(this Enum enumValue, Type enumType) 
    { 
     string displayName = ""; 
     MemberInfo info = enumType.GetMember(enumValue.ToString()).First(); 

     if (info != null && info.CustomAttributes.Any()) 
     { 
      DisplayAttribute nameAttr = info.GetCustomAttribute<DisplayAttribute>(); 
      displayName = nameAttr != null ? nameAttr.Name : enumValue.ToString(); 
     } 
     else 
     { 
      displayName = enumValue.ToString(); 
     } 
     return displayName; 
    } 
} 

Dann können Sie es wie folgt verwenden:

Notebook n = Notebook.NotebookHP; 
String displayName = n.GetDisplayAttributeFrom(typeof(Notebook)); 

EDIT: Unterstützung für die Lokalisierung

Dies kann nicht die effizienteste Weg, aber sollte arbeiten.

public static class EnumExtensions 
{ 
    public static string GetDisplayAttributeFrom(this Enum enumValue, Type enumType) 
    { 
     string displayName = ""; 
     MemberInfo info = enumType.GetMember(enumValue.ToString()).First(); 

     if (info != null && info.CustomAttributes.Any()) 
     { 
      DisplayAttribute nameAttr = info.GetCustomAttribute<DisplayAttribute>(); 

      if(nameAttr != null) 
      { 
       // Check for localization 
       if(nameAttr.ResourceType != null && nameAttr.Name != null) 
       { 
        // I recommend not newing this up every time for performance 
        // but rather use a global instance or pass one in 
        var manager = new ResourceManager(nameAttr.ResourceType); 
        displayName = manager.GetString(nameAttr.Name) 
       } 
       else if (nameAttr.Name != null) 
       { 
        displayName = nameAttr != null ? nameAttr.Name : enumValue.ToString(); 
       } 
      } 
     } 
     else 
     { 
      displayName = enumValue.ToString(); 
     } 
     return displayName; 
    } 
} 

Auf der ENUM muss der Schlüssel und Ressourcentyp angegeben werden:

[Display(Name = "MyResourceKey", ResourceType = typeof(MyResourceFile)] 
+0

Funktioniert wie ein Charme! :) Vielen Dank. – developer033

+1

Es funktioniert nicht :(// "ResourceType ist ein 'Typ', aber wird wie eine 'Variable' verwendet. Und was ist ResFileAssembly? – developer033

+0

Meine Antwort aktualisiert, das' new' Schlüsselwort für den Ressourcenmanager hinzugefügt und verwende die Der Ressourcentyp wurde in der Annotation der Enumeration durch den 'ResourceType' spezifiziert. Ich habe das lokal getestet und es funktioniert. – akousmata

1

Da Sie Visuals sind besorgniserregend würde ich einen konfigurierbaren Ansatz verwenden:

public NotebookTypes NotebookType; 

public enum NotebookTypes{ 
    NotebookHP, 
    NotebookDell 
} 

public string NotebookTypeName{ 
    get{ 
     switch(NotebookType){ 
     case NotebookTypes.NotebookHP: 
      return "Notebook HP"; //You may read the language dependent value from xml... 
     case NotebookTypes.NotebookDell: 
      return "Notebook Dell"; //You may read the language dependent value from xml... 
     default: 
      throw new NotImplementedException("'" + typeof(NotebookTypes).Name + "." + NotebookType.ToString() + "' is not implemented correctly."); 
     } 
    } 
} 
+0

Ich habe deine Antwort verstanden, aber ist der einzige Weg? (Wenn ich 15 Enums habe, muss ich es für alle machen). Übrigens, ich mache mir Sorgen wegen Visual, weil ich ein paar Enums habe: 'HigherEducationIncomplete', ich finde es schrecklich, ich will nur 'Higher Education' zeigen Unvollständig '(wie ich in DisplayAttribute konfiguriert habe), können Sie jetzt verstehen? – developer033

+0

@ developer033 Nein, sicher nicht. Mit diesem Ansatz können Sie die Visuals für Multifile-Sprachen konfigurieren. –

+0

Es funktioniert mit der @akousmata Antwort. Wie auch immer, danke, +1 für den Versuch. – developer033

2

Hier ist eine vereinfachte (und arbeiten) Version von akousmata ENUM Erweiterung lokalisiert:

public static string DisplayName(this Enum enumValue) 
{ 
    var enumType = enumValue.GetType(); 
    var memberInfo = enumType.GetMember(enumValue.ToString()).First(); 

    if (memberInfo == null || !memberInfo.CustomAttributes.Any()) return enumValue.ToString(); 

    var displayAttribute = memberInfo.GetCustomAttribute<DisplayAttribute>(); 

    if (displayAttribute == null) return enumValue.ToString(); 

    if (displayAttribute.ResourceType != null && displayAttribute.Name != null) 
    { 
     var manager = new ResourceManager(displayAttribute.ResourceType); 
     return manager.GetString(displayAttribute.Name); 
    } 

    return displayAttribute.Name ?? enumValue.ToString(); 
} 

Hinweis: Ich verschiebe enumType von einem Parameter in eine lokale Variable.

Beispiel Nutzung:

public enum IndexGroupBy 
{ 
    [Display(Name = "By Alpha")] 
    ByAlpha, 
    [Display(Name = "By Type")] 
    ByType 
} 

Und

@IndexGroupBy.ByAlpha.DisplayName() 

Hier ist ein Editor-Vorlage, die oben mit der Erweiterung Verfahren verwendet werden können:

@model Enum 

@{  
    var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e => 
     new SelectListItem 
     { 
      Text = e.DisplayName(), 
      Value = e.ToString(), 
      Selected = e.Equals(Model) 
     }); 
    var prefix = ViewData.TemplateInfo.HtmlFieldPrefix; 
    var index = 0; 
    ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty; 

    foreach (var li in listItems) 
    { 
     var fieldName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++); 
     <div class="editor-radio"> 
      @Html.RadioButton(prefix, li.Value, li.Selected, new {@id = fieldName}) 
      @Html.Label(fieldName, li.Text) 
     </div> 
    } 
    ViewData.TemplateInfo.HtmlFieldPrefix = prefix; 
} 

Und hier ist ein Beispiel für die Verwendung :

@Html.EditorFor(m => m.YourEnumMember, "Enum_RadioButtonList") 
+1

Guter Fang, um den Typ direkt aus der Enum zu bekommen. Viel sauberer Ansatz. – akousmata