How to set and change the culture in WPF

Viewed 30511

I have a .NET 4.0 WPF application where the user can change the language (culture) I simply let the user select a language, create a corresponding CultureInfo and set:

Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;

In the C# code this works fine. However in the WPF controls the culture is still en-US. This means for example that dates will be shown in the US format instead of whatever is correct for the current culture.

Apparently, this is not a bug. According to MSDN and several blog posts and articles on StackOverflow the WPF language does not automatically follow the current culture. It is en-US until you do this:

FrameworkElement.LanguageProperty.OverrideMetadata(
    typeof(FrameworkElement),
    new FrameworkPropertyMetadata(
        XmlLanguage.GetLanguage(CultureInfo.CurrentUICulture.IetfLanguageTag)));

See for example StringFormat Localization issues in wpf.

I do not completely understand what is going on here. It seems the Language property on all frameworkelements is set to the current culture. Anyway, it works. I do this when the application starts up and now all controls works as expected, and e.g. dates is formatted according to the current culture.

But now the problem: According to MSDN FrameworkElement.LanguageProperty.OverrideMetadata can only be called once. And indeed, if I call it again (when the user changes the language) it will throw an exception. So I haven't really solved my problem.

The question: How can I reliably update the culture in WPF more than once and at any time in my applications life cycle?

(I found this when researching: http://www.nbdtech.com/Blog/archive/2009/03/18/getting-a-wpf-application-to-pick-up-the-correct-regional.aspx and it seems he has something working there. However, I can't imagine how to do this in my application. It seems I would have to update the language in all open windows and controls and refresh all existing bindings etc.)

8 Answers

I use the merged resource dictionary/dynamic resource appproach to change my strings. But for correct automatic date/time/other regional formatting I am setting the language on Application.Current.MainWindow.Language, it gets inherited by the children and updates automatically. At least on Net 5.0...

var l = System.Globalization.CultureInfo.CreateSpecificCulture(localeName);
                
Thread.CurrentThread.CurrentUICulture = l;
Thread.CurrentThread.CurrentCulture = l;
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = l;
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = l;
// Order is important!!! Set Threads before MainWindow.Language, 
// otherwise regional settings are inconsistent

Application.Current.MainWindow.Language = XmlLanguage.GetLanguage(l.Name);

Related