Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum in WPF ComboxBox with localized names

I have a ComboBox listing an Enum.

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

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

I want to display localized names for the enum values in English

Open
Closed
In Progress

but also in German (and other languages in the future)

Offen
Geschlossen
In Arbeit

In my ViewModel using

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

only gets me the names of the enum in the code and not the translated ones.

I have general localization in place and can access them using i.e.

Resources.Strings.InProgress

which gets me the translation for the current language.

How can I bind the localization automatically?

like image 229
juergen d Avatar asked Apr 15 '15 19:04

juergen d


People also ask

How do I change the ComboBox style in WPF?

In visual studio, open WPF designer, select combo box control, then right click combo box control and select Edit template, then select Edit a Copy. This will create a style template, you can modify it as you need.

How do I add a ComboBox item in WPF?

On button click event handler, we add the content of TextBox to the ComboBox by calling ComboBox. Items. Add method. Now if you enter text in the TextBox and click Add Item button, it will add contents of the TextBox to the ComboBox.

What is ComboBox in WPF?

A combobox is a selection control that combines a non-editable textbox and a drop-down listbox that allows users to select an item from a list. It either displays the current selection or is empty if there is no selected item.


2 Answers

It's an example of the simple Enum to translated string converter.

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");
    }
}

Also you need a MarkupExtension which will provide values:

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: You can make a more complex value converter and markup extension. The EnumToStringConverter can use DescriptionAttribute's to get the translated strings. And the EnumerateExtension can use TypeConverter.GetStandardValues() and a converter. This allows to get standard values of the specified type (not only Enums) and convert them to strings or something another depending on the converter.

Example:

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

EDIT: The more complex solution described above is published on GitHub now.

like image 76
Yoh Deadfall Avatar answered Sep 18 '22 10:09

Yoh Deadfall


You can do using a Attribute for the enum and writing an extension method for the enum. Refer the below code.

<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.
        }
    }

I have already posted a similar thing in SO Is it possible to databind to a Enum, and show user-friendly values?

like image 23
Ayyappan Subramanian Avatar answered Sep 22 '22 10:09

Ayyappan Subramanian