2015-04-15 18 views
12

Ho un ComboBox che elenca un Enum.Enum in WPF ComboxBox con nomi localizzati

enum StatusEnum { 
    Open = 1, Closed = 2, InProgress = 3 
} 

<ComboBox ItemsSource="{Binding StatusList}" 
      SelectedItem="{Binding SelectedStatus}" /> 

voglio visualizzare nomi localizzati per i valori enum in inglese

Open 
Closed 
In Progress 

ma anche in tedesco (e altre lingue in futuro)

Offen 
Geschlossen 
In Arbeit 

Nel mio ViewModel utilizzando

public IEnumerable<StatusEnum> StatusList 
{ 
    get 
    { 
     return Enum.GetValues(typeof(StatusEnum)).Cast<StatusEnum>(); 
    } 
} 

mi ottiene solo i nomi dell'enumerazione nel codice e non quelli tradotti.

devo localizzazione generale nel posto e possono accedervi utilizzando cioè

Resources.Strings.InProgress 

che mi ottiene la traduzione per la lingua corrente.

Come si può associare automaticamente la localizzazione?

+0

Avete già installato un sistema di localizzazione? Se sì, dettagli? O dovremmo semplicemente portarti a un metodo 'String GetValue (StatusEnum status)' e lasciarti localizzare da lì? –

+0

Ho localizzazione sul posto. Ho solo bisogno di capire per enumerare Binding, –

risposta

14

Si tratta di un esempio di semplice Enum al convertitore stringa tradotta.

public sealed class EnumToStringConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
     { return null; } 

     return Resources.ResourceManager.GetString(value.ToString()); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     string str = (string)value; 

     foreach (object enumValue in Enum.GetValues(targetType)) 
     { 
      if (str == Resources.ResourceManager.GetString(enumValue.ToString())) 
      { return enumValue; } 
     } 

     throw new ArgumentException(null, "value"); 
    } 
} 

hai bisogno anche di un MarkupExtension che fornirà valori:

public sealed class EnumerateExtension : MarkupExtension 
{ 
    public Type Type { get; set; } 

    public EnumerateExtension(Type type) 
    { 
     this.Type = type; 
    } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     string[] names = Enum.GetNames(Type); 
     string[] values = new string[names.Length]; 

     for (int i = 0; i < names.Length; i++) 
     { values[i] = Resources.ResourceManager.GetString(names[i]); } 

     return values; 
    } 
} 

Usage:

<ComboBox ItemsSource="{local:Enumerate {x:Type local:StatusEnum}}" 
      SelectedItem="{Binding SelectedStatus, Converter={StaticResource EnumToStringConverter}}" /> 

EDIT: È possibile effettuare una più complessa convertitore di valori e di markup estensione. EnumToStringConverter può utilizzare DescriptionAttribute per ottenere le stringhe tradotte. E lo EnumerateExtension può utilizzare TypeConverter.GetStandardValues() e un convertitore. Ciò consente di ottenere valori standard del tipo specificato (non solo Enum s) e convertirli in stringhe o qualcosa di diverso a seconda del convertitore.

Esempio:

<ComboBox ItemsSource="{local:Enumerate {x:Type sg:CultureInfo}, Converter={StaticResource CultureToNameConverter}}" 
      SelectedItem="{Binding SelectedCulture, Converter={StaticResource CultureToNameConverter}}" /> 

EDIT: La soluzione più complesso sopra descritto è pubblicato GitHub ora.

+0

Questa è una grande soluzione a livello di vista – Tseng

2

Non è possibile, fuori dalla scatola.

Ma è possibile creare una proprietà ObservableList<KeyValuePair<StatusEnum, string>> e riempirla con il proprio enum/testo localizzato e quindi associarlo al numero ComboBox.

Per quanto riguarda la stringa stessa:

var localizedText = (string)Application.Current.FindResource("YourEnumStringName"); 

Ottenere la rappresentazione di stringa Enum con Enum.GetName/Enum.GetNames metodi.

1

È possibile utilizzare un attributo per l'enumerazione e scrivere un metodo di estensione per l'enumerazione. Fare riferimento al codice seguente.

<ComboBox Width="200" Height="25" ItemsSource="{Binding ComboSource}" 
      DisplayMemberPath="Value" 
      SelectedValuePath="Key"/> 


public class MainViewModel 
{ 
    public List<KeyValuePair<Status, string>> ComboSource { get; set; } 

    public MainViewModel() 
    { 
     ComboSource = new List<KeyValuePair<Status, string>>(); 
     Status st=Status.Open; 
     ComboSource = re.GetValuesForComboBox<Status>(); 
    } 
} 

public enum Status 
{ 
    [Description("Open")] 
    Open, 
    [Description("Closed")] 
    Closed, 
    [Description("InProgress")] 
    InProgress 
} 

public static class ExtensionMethods 
    { 
     public static List<KeyValuePair<T, string>> GetValuesForComboBox<T>(this Enum theEnum) 
     { 
      List<KeyValuePair<T, string>> _comboBoxItemSource = null; 
      if (_comboBoxItemSource == null) 
      { 
       _comboBoxItemSource = new List<KeyValuePair<T, string>>(); 
       foreach (T level in Enum.GetValues(typeof(T))) 
       { 
        string Description = string.Empty; 
        FieldInfo fieldInfo = level.GetType().GetField(level.ToString()); 
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 
        if (attributes != null && attributes.Length > 0) 
        { 
         Description = GetDataFromResourceFile(attributes.FirstOrDefault().Description); 
        } 
        KeyValuePair<T, string> TypeKeyValue = new KeyValuePair<T, string>(level, Description); 
        _comboBoxItemSource.Add(TypeKeyValue); 
       } 
      } 
      return _comboBoxItemSource; 
     } 

     public static string GetDataFromResourceFile(string key) 
     { 
      //Do you logic to get from resource file based on key for a language. 
     } 
    } 

Ho già postato una cosa simile in SO Is it possible to databind to a Enum, and show user-friendly values?

Problemi correlati