Ich bin nicht sicher, was Sie unter „Das ist komplexer als meine ideale Lösung“. Ich habe einen Weg, dies anders zu machen als deins, aber es ist vielleicht nicht weniger komplex. Ich würde sagen, dass mein Weg mehr Aufwand im Voraus bedeutet, aber zahlt sich aus, je mehr Sie es in Ihrer Anwendung verwenden. Es bereitet Ihre Anwendung so vor, dass sie lokalisierbar ist, und bedeutet, dass Sie nicht jedem Enum-Wert Attribute hinzufügen müssen. Machen
1) einen Resource Manager Cache
Dieser Teil ist optional; Wenn Sie jedoch mehrere Ressourcendateien mehrmals verwenden, kann dies die Leistung erhöhen, indem Sie die Anzahl der Reflektionen verringern.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
namespace AppResourceLib.Public.Reflection
{
internal static class ResourceManagerCache
{
private static Dictionary<Type, ResourceManager> _resourceManagerMap =
new Dictionary<Type, ResourceManager>();
public static ResourceManager GetResourceManager(Type resourceType)
{
ResourceManager resourceManager = null;
// Make sure the type is valid.
if (null != resourceType)
{
// Try getting the cached resource manager.
if (!ResourceManagerCache._resourceManagerMap.TryGetValue(resourceType, out resourceManager))
{
// If it is not in the cache create it.
resourceManager = resourceType.InvokeMember(
"ResourceManager",
(BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic),
null,
null,
null) as ResourceManager;
// If it was created, add the resource manager to the cache.
if (null != resourceManager)
{
ResourceManagerCache._resourceManagerMap.Add(resourceType, resourceManager);
}
}
}
return resourceManager;
}
}
}
2) Erstellen Sie ein Lokalisierte Beschreibung Attribut
Dies ist das Attribut, das Sie auf den Enum-Typen gelten. Das coole daran ist, dass Sie nicht jedem Enum ein Attribut hinzufügen müssen, nur einmal über der Enum-Typ-Deklaration.
using System;
using System.ComponentModel;
namespace AppResourceLib.Public.Reflection
{
/// <summary>
/// A resource type attribute that can be applied to enumerations.
/// </summary>
[AttributeUsage(AttributeTargets.Enum)]
public sealed class LocalizedDescriptionAttribute : Attribute
{
/// <summary>
/// The type of resource associated with the enum type.
/// </summary>
private Type _resourceType;
public LocalizedDescriptionAttribute(Type resourceType)
{
this._resourceType = resourceType;
}
/// <summary>
/// The type of resource associated with the enum type.
/// </summary>
public Type ResourceType
{
get
{
return this._resourceType;
}
}
}
}
3) erstellen Lokalisierte Beschreibung Converter
Dieser wandelt den Enum-Wert in den String werden Sie es in der Strings Ressource geben (RESX-Datei).
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Windows.Data;
namespace AppResourceLib.Public.Reflection
{
[ValueConversion(typeof(Object), typeof(String))]
public class LocalizedDescriptionConverter : IValueConverter
{
public Object Convert(Object value, Type targetType, Object param, CultureInfo cultureInfo)
{
String description = null;
if (null != value)
{
// If everything fails then at least return the value.ToString().
description = value.ToString();
// Get the LocalizedDescriptionAttribute of the object.
LocalizedDescriptionAttribute attribute =
value.GetType().GetCustomAttribute(typeof(LocalizedDescriptionAttribute))
as LocalizedDescriptionAttribute;
// Make sure we found a LocalizedDescriptionAttribute.
if (null != attribute)
{
ResourceManager resourceManager =
ResourceManagerCache.GetResourceManager(attribute.ResourceType);
if (null != resourceManager)
{
// Use the ResourceManager to get the description you gave the object value.
// Here we just use the object value.ToString() (the name of the object) to get
// the string in the .resx file. The only constraint here is that you have to
// name your object description strings in the .resx file the same as your objects.
// The benefit is that you only have to declare the LocalizedDescriptionAttribute
// above the object type, not an attribute over every object.
// And this way is localizable.
description = resourceManager.GetString(value.ToString(), cultureInfo);
String formatString = (param as String);
// If a format string was passed in as a parameter,
// make a string out of that.
if (!String.IsNullOrEmpty(formatString))
{
formatString = formatString.Replace("\\t", "\t");
formatString = formatString.Replace("\\n", "\n");
formatString = formatString.Replace("\\r", "\r");
description = String.Format(formatString, value.ToString(), description);
}
}
}
}
return description;
}
public Object ConvertBack(Object value, Type targetType, Object param, CultureInfo cultureInfo)
{
throw new NotImplementedException();
return null;
}
}
}
4) Erstellen Sie eine Ressource (RESX) String Datei
Jetzt können Sie eine Ressource-Datei erstellen möchten, die die Beschreibungen Sie für Ihre Aufzählungen Schlüsselwert Stil enthält. Was ich damit meine, ist, dass Sie in der "Name" -Spalte der String-Ressourcen den genauen Namen der einzelnen Enums eingeben und in der "Value" -Spalte die Zeichenfolge angeben, die Sie beim Konvertieren dieser Enumeration erhalten möchten.
Zum Beispiel sagen, Sie hatten die folgenden Enums.
public enum MyColors
{
Black,
Blue,
White
}
Dann würde die Zeichenfolge-Ressource-Datei wie folgt aussehen ...
Name | Wert
Schwarz | Eine dunkle Farbe
Blau | Eine coole Farbe
Weiß | Eine helle Farbe
5) Erstellen Sie Aufzählungen mit Attribute
Jetzt sind wir mit dem LocalizedDescription schließlich die Enum-Deklaration machen. Der Parameter, den Sie an das LocalizedDescription-Attribut übergeben, ist der Typ der Zeichenfolge-Ressourcendatei. Jetzt, wenn der Konverter verwendet wird, sieht er das Attribut des Aufzählungstyps, ruft die Ressourcendatei ab, sucht nach der Schlüsselzeichenfolge, die mit dem Zeichenfolgenwert des bestimmten Aufzählungswerts übereinstimmt, und gibt den Wert aus der Ressourcendatei als konvertierte Zeichenfolge zurück.
using AppResourceLib.Public;
using AppResourceLib.Public.Reflection;
namespace MyEnums
{
[LocalizedDescription(typeof(MyColorStrings))]
public enum MyColors
{
Black,
Blue,
White
}
}
Der große Nachteil dieses Ansatzes ist, dass es funktioniert nur, wenn die „Name“ Schlüssel in der Ressource-Datei die Namen Ihrer ENUM-Werte entsprechen. Dies ist die einzige Möglichkeit, auf Zeichenfolgenwerte in einer Ressourcendatei zu verweisen, ohne dass jeder Enumeration ein Beschreibungsattribut zugewiesen wird. Wie benutzt du das für die Anzeige von Werten? Hier ist ein Beispiel ...
In Ihrem XAML-Code möchten Sie einen Datenprovider erstellen, um die Werte der Enums auf Ihr UI-Element zu bekommen (ich benutze hier eine ComboBox ...). Dann sollten Sie den Konverter verfügbar machen und Ihr UI-Element für die Verwendung des Enum-Konverters vorbereiten. So, hier geht es ...
<!-- Enum Colors -->
<ObjectDataProvider x:Key="MyColorEnums"
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="MyColors"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<!-- Enum Type Converter -->
<LocalizedDescriptionConverter x:Key="EnumConverter"/>
<!-- Dropdown Expand ComboBox Template -->
<DataTemplate x:Key="MyColorsComboBoxTemplate">
<Label Content="{Binding Path=., Mode=OneWay,
Converter={StaticResource EnumConverter}}"
Height="Auto" Margin="0" VerticalAlignment="Center"/>
</DataTemplate>
<!-- And finally the ComboBox that will display all of your enum values
but will use the strings from the resource file instead of enum.ToString() -->
<ComboBox Width="80" HorizontalAlignment="Left"
ItemTemplate="{StaticResource MyColorsComboBoxTemplate}"
ItemsSource="{Binding Source={StaticResource MyColorEnums}}">
Wow, sorry das so lang ist. Ich bin mir nicht sicher, ob dies für Sie zu komplex ist, aber es ist eine andere Option. Ich hoffe es hilft!
Vielleicht sollten Sie diese Methode ausprobieren: http://en.wikipedia.org/wiki/Rubber_duck_debugging – espais
möglich Duplikat von [Wie überschreibe ich ToString in C# enums?] (Http://stackoverflow.com/questions/796607/how-do-i-override-Zahnring-in-c-sharp-enums) –
Definethely nicht verwandt. Die Lösung für die Antwort in diesem Thread ist bereits oben implementiert. Diese Frage geht viel weiter. – greggorob64