In my “A Better Way to Data Bind Enums in WPF” post, I showed how we could use a combination of a custom MarkupExtention and TypeConverter to more easily data bind an ItemsControl to an Enum and display a custom description for each Enum value. The result looked something like this:
I have recently received a question related to that post on how to go about adding support for localizing those descriptions. Well, it just so happens to be extremely easy. We will be building on top of the previous Enum sample from the previous post. Let’s see what it take to localize enum descriptions in WPF.
Adding Localization Support
The first thing we need to do in order to localize enum descriptions is to create a custom Attribute. I called mine LocalizedDescriptionAttribute, and it looks like this:
{
ResourceManager _resourceManager;
string _resourceKey;
public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
{
_resourceManager = new ResourceManager(resourceType);
_resourceKey = resourceKey;
}
public override string Description
{
get
{
string description = _resourceManager.GetString(_resourceKey);
return string.IsNullOrWhiteSpace(description) ? string.Format(“[[{0}]]”, _resourceKey) : description;
}
}
}
This custom attribute derives from the already existing DescriptionAttribute. This allows us to override the Description property to provide our own implementation. We are expecting a resourceKey which will be the unique name defined in our Resources.resx file. We also need to know which Resource object to use, since you can create any number of uniquely named resource files in your application. We then rely on the built-in ResourceManager, given the correct resourceType, to get the correct value depending on the current culture information.
Go ahead and add a coupld of Resource.resx files to the project and target your desired cultures.
EnumResources.resx (English)
EnumResources.ja-JP.resx (Japanese)
Now that we have our resource files, we need to modify our Enum to include the LocalizedDescriptionAttribute. I will only modify the last three values.
public enum Status
{
[Description(“This is horrible”)]
Horrible,
[Description(“This is bad”)]
Bad,
[Description(“This is so so”)]
SoSo,
[LocalizedDescription(“Good”, typeof(EnumResources))]
Good,
[LocalizedDescription(“Better”, typeof(EnumResources))]
Better,
[LocalizedDescription(“Best”, typeof(EnumResources))]
Best
}
Go ahead and run the code. You should notice no change in the values themselves, but you will notice the values are being retrieved from our EnumResources.resx file.
Now, go ahead and go into the App.xaml.cs and override the OnStartup method, and change the current CultureInfo.
{
CultureInfo info = new CultureInfo(“ja-JP”);
Thread.CurrentThread.CurrentCulture = info;
Thread.CurrentThread.CurrentUICulture = info;
}
Now run the app again.
Now we can visually see our LocalizedDescriptionAttribute at work. That’s it! That’s all it takes to localize enum descriptions in WPF. Hopefully you will find this useful, and maybe even use this approach in your WPF applications. Be sure to check out the source code, and start playing with it. As always, feel free contact me on my blog, connect with me on Twitter (@brianlagunas), or leave a comment below for any questions or comments you may have.
Very elegant.
But how can I bind SelectedValue in my combobox ?
I want to bind the values Good/Better/Best.
You bind to it like you would bind any other property. Just bind to the SelectedItem/SelectedValue property as needed.
Thank you for the reply, but I cannot get it working. I bind the SelectedItem, but I need a converter to convert the value ‘good’ to the Enum value ‘good’.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (Status)Enum.Parse(typeof(Status), value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
What am I missing ?
You don’t need any converters. Just bind the ComboBox.SelectedItem to your Enum property that is in your ViewModel.