65.9K
CodeProject is changing. Read more.
Home

WPF : Binding to an enum with localization

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (5 votes)

May 2, 2014

CPOL

2 min read

viewsIcon

29912

downloadIcon

329

This article shows how to add a Combobox binded to an enum in a WPF control or application, in a very simple, and reusable way.

Introduction

I wrote this article because I tried to find a way to easily add a Combobox which is binded on enum typed data : SelectedValue is an enum typed property, and possible values are all the enum values. This is very simple and very oftently described in many articles / forum on the web, but there was no simple way to couple this with the possibility to localize enum values... And I found a very simple, and reusable solution to do this !

Using the code

The first part of the solution (binding a Combobox to an enum property by giving the user the possibility to chose between all the enum possible values) is very classic:

In XAML:

    <Window.Resources>
        <ObjectDataProvider MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}"
                        x:Key="MyEnumValues">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:MyEnum" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center"  
                    ItemsSource="{Binding Source={StaticResource MyEnumValues}}"
                    SelectedValue="{Binding EnumProp, Mode=TwoWay}" />
    </Grid>   

and corresponding C# code:

    public enum MyEnum
    {
        EnumVal1,
        EnumVal2,
        EnumVal3,
    }
   
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataContext = this;
            InitializeComponent();
        }

        MyEnum _EnumProp = MyEnum.EnumVal2;
        public MyEnum EnumProp
        {
            get { return _EnumProp; }
            set { _EnumProp = value; }
        }
    } 

With that code, you will obtain this Combobox :

The second part is the more interresing one (the one for which I did not succeed in finding any satisfying solution on any forum :-() will show a very simple and reusable solution pemitting to display a localized string for each enum value :

The idea is to use a generic converter to get localizable string values corresponding to enum values : this converter will try to find the string value in the current WPF application resources with a key which depends on the enum identifier :

using System;
using System.Windows;
using System.Windows.Data;

namespace LocalizedWPFComboBox
{
    /// <summary>
    /// This converter will try to find a string value in the current WPF application 
    ///     resources with a key which depends on the enum identifier
    /// </summary>
    public class Enum2LocalizedStringConverter : IValueConverter
    {
        public object Convert(  object value, Type targetType, object parameter,
                                System.Globalization.CultureInfo culture)
        {
            if (value != null)
            {
                // Build a resource key based on the enum type and value
                string Key = value.GetType().ToString() + "_" + value.ToString() + "_Traduction";
                // Try to find the traduction in the current application resources
                string Traduction = Application.Current.TryFindResource(Key) as string;
                if (Traduction == null)
                    // Traduction could not be found in the current application resources
                    return "Enum2LocalizedStringConverter : " + Key + " could not be found !!";
                return Traduction;
            }
            // return empty string if value is null
            return "";
        }

        public object ConvertBack(  object value, Type targetType, object parameter, 
                                    System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
In the case of our example, this converter will try to find string resources with the keys LocalizedWPFComboBox.MyEnum_EnumVal1_Traduction for EnumVal1 value, LocalizedWPFComboBox.MyEnum_EnumVal2_Traduction for EnumVal2 value, etc... This XAML Dictionary can be used for example to traduce our enum values (excuse me but I'm french ;-) ) :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <!-- EditableType enum traductions -->
    <sys:String x:Key="LocalizedWPFComboBox.MyEnum_EnumVal1_Traduction">Traduction française pour l'ID 'EnumVal1'</sys:String>
    <sys:String x:Key="LocalizedWPFComboBox.MyEnum_EnumVal2_Traduction">EnumVal2 : merci qui ?</sys:String>
    <sys:String x:Key="LocalizedWPFComboBox.MyEnum_EnumVal3_Traduction">EnumVal3 : merci Olivier ;-D</sys:String>
</ResourceDictionary>

With this converter and the associated string resources values, you just have to set the Combobox ItemTemplate with a TextBlock which uses the converter to display enum values :

        <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center"  
                    ItemsSource="{Binding Source={StaticResource MyEnumValues}}"
                    SelectedValue="{Binding EnumProp, Mode=TwoWay}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Converter={StaticResource Enum2LocalizedStringConverter}}" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

With the final code described in this article, you will obtain this (localized) ComboBox :

Points of Interest

In my developments, I use this converter in a base library which is used in any projetcs : like this, configure the converter for any WPF Control binded to an enum, define the corresponding enum traduction in resources of the application, and it works !

History

2 May 2014 : creation of the article.