Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

WPF Bindings and CurrentCulture Formatting


:P
On this page:

I was surprised to find today that while putting together some localization samples that by default WPF bindings do not respect the current culture. For example check out this localized form that has been localized to German and is running with both Culture and UICulture in the de-DE locale:

  BindingsFormattingMess

If you look at the highlighted formatting text you’ll notice that the form is localized (ie.the UICulture is applied) and that the active culture which in this case displays the CultureInfo.CurrentCulture is also set to German. But as you can see the date and number format is clearly using the default en-US formatting.

Apparently this is by design in WPF, although I can’t think of a single reason why this behavior should be so. Every other UI environment correctly assumes that if you have your culture set to a specific locale you’ll want your formatting and conversions to apply using this culture. But no that would be, uh too easy and nothing in WPF is easy after all.

Well, maybe it is, since the solution is relatively simple. All WPF elements include a Language property that can be assigned and determines the Culture that is used for formatting. The property is applied down the container hierarchy so setting the language at the top level container like the on the Window in the above form is all that’s needed.

Here’s the one liner:

this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);

Easy enough but not something that search turned up real easily. Just another one of those issues I fretted over for a couple of hours experimenting that makes WPF such an incredible time sink.

Note that it’s important that the language assignment happens before InitializeComponent in the constructor because the language is applied at load time:

public LocalizationInfo()
{    
    // MAKE SURE you set the language of the page explicitly or else
    // all number and date formatting occurs using the neutral culture 
    this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);

    InitializeComponent();
    
    this.Loaded += LocalizationInfo_Loaded;            
}

You can also set the language globally for your entire application in the App class:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    // Set application startup culture based on config settings
    string culture = ConfigurationManager.AppSettings["Culture"];
    SetCulture(culture);

    Theme = ConfigurationManager.AppSettings["Theme"];
    SetTheme(Theme);

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

This will switch the default language for the entire application. You’ll want to use this only in startup code as this setting can be applied only once per application. You can still override individual forms when necessary using the explicit language override shown above.

Hopefully this will help somebody out by making this issue more readily findable.

And no jokes about my funky German localization. Even though I speak German fluently localizing a computer form is definitely not something I feel qualified for :-}.

Posted in WPF  Localization  

The Voices of Reason


 

The Luddite Developer
June 15, 2009

# re: WPF Bindings and CurrentCulture Formatting

Good Find.

The only point I would make is that numeric date formats should never be used in an international environment.

In global terms a numeric only date format like 01/06/2008 is completely ambiguous. It means 6th January 2008 in some parts of the World and the 1st of June in most other parts of the World. Either version of 01-Jun-2008 or Jun-01-2008 is vastly more informative, my preference is to use 01-Jun-2008 as a more acceptable global date format.

Of course the month abbreviations must also be translated for internation use.

Rick Strahl
June 15, 2009

# re: WPF Bindings and CurrentCulture Formatting

But isn't that the whole point of CurrentCulture? If you have a desktop app and you adjust it to the local culture then the date format (including numeric dates) should make sense, no?

It's a different story in Web apps where you are absolutely right because you're not likely to be able to capture everybody's locale accurately.

Do like the date format you're proposing as a general rule and we're just giving up 1 extra character for the more readable version. This is a custom date format string right (dd-MMM-yyyy)?

The Luddite Developer
June 15, 2009

# re: WPF Bindings and CurrentCulture Formatting

You are absolutely right about CurrentCulture, however there are a number of exceptions that can lead to ambiguity in any corporate environment. For example,

1. Who own the laptop and where was it set up?
2. European employee working in US forgets or does not know that US have a different date format.
3. US employee working in Europe forgets or does not know that UK have a different date format.
4. Variable programming standards, how can we be sure that the local culture is being used.

As you said, it is mostly a problem with world wide web applications, but there are destop applications out there that just cannot be trusted. How can an application user be certain?

Yes the format used is dd-MMM-yyyy.

JM
June 16, 2009

# re: WPF Bindings and CurrentCulture Formatting

That's not entirely correct.
In some countries the official and proper way to display dates is established by law and is important that software follows the law, especially for software used in public service, which happens to be the largest consumers of programs.

The fact that WPF's controls don't follow the CurrentCulture is a biggie and is a defect that should be addressed, but as Mr. Strahl pointed out, it's by design, so it's not likely to change (and I would like to choke the guy who decided that, since I had to debug a large app suite that makes use of different programs written in different frameworks, and the WPF ones wouldn't follow what the control panel stated). It's especially annoying the fact that it's only WPF that does that. If all of the controls in the whole .NET framework would do that, it would be one thing, but it's not the case.

The points you brought up are user training issues, and shouldn't be addressed by jacking around with the framework.

On a totally unrelated issue, Mr. Strahl, when I look at the comment preview, I see at the bottom the "Remember Me" checkbox, and the following text:
1253 of <%= App.Configuration.CommentMaxLength %> characters

Thought you might wanna know..

AC
June 16, 2009

# re: WPF Bindings and CurrentCulture Formatting

Rick, out of curiosity, what is it defaulting to? Your machine's current culture, or the invariant culture?

This has always been a sticky situation. I'd almost prefer that there was no default in C# to force developers to always think everytime they emit a DateTime, or if the defaults were to use an invariant culture so that any presentation errors are easily corrected, but config files and other text processing isn't affected, or was already dealt with and doesn't change 'by accident' when switching the regional settings.

Like the luddite, I vote to be rid of completely numeric dates altogether. dd-MMM-yyyy is understandable by most.

Phillip H
June 17, 2009

# re: WPF Bindings and CurrentCulture Formatting

Rick,

I've been following your difficulties with WPF through your blog but cannot unfortunately help you on the internationalisation; however I would be intrigued to know how you feel the process of development in WPF compares to WinForms/AJAX WebForms - does it actually turn out to be longer to build an application ? For my part, I have consistently found my programming teams take 2-3 times longer to build a WebForms based application than a WinForms based one (even a multi-tier web forms one), just because of the aggravation and "friction" of developing browser based systems. Of course that doesn't mean one is somehow superior as a development paradigm or toolset, but I would have expected a new technique such as WPF (and by extension Silverlight) to close the programmer-efficiency gap. Have you any opinion on whether its made it easier/faster ?

Phil H

Rick Strahl
June 17, 2009

# re: WPF Bindings and CurrentCulture Formatting

@Phillip - at the stage I'm at WPF takes me infinitely LONGER than either WinForms or WebForms. For me Web development and WinForms dev are roughly on par in terms or dev speed are roughly on par with WinForms maybe a little speedier, but it's probably a case where what you know will get you there quicker.

WPF is problematic for me in a number of ways: a) The time it takes to lay out UI takes much much longer than WinForms. I suppose if I wanted to compare apples to apples I could use Canvas for everything and do positional layout which would speed things up but negate some of the advantages of WPF. And b) WPF is very, very complex and there are many inconsistencies and quirks like this one mentioned in this post that make you go WTF were they thinking? These by far are the biggest time sinks sometimes taking hours to resolve or even understand. Additionally it seems like the WPF teams are not good at listening to customer feedback as the pain points that people are running into have not been addressed in 3 years and 2 updates since WPF has been out.

WPF is interesting because there's so much that you CAN do with it and so much control you have over the environment, but it's so complex that it takes a long time to understand all the details. Everytime I start with it I find something where I go, man this is so cool and this makes my life so much easier, only to be slapped down by some other feature that's lacking a crucial piece as to be worthless. It's a mixed bag, but the learning curve for me at least has been intense and honestly I can't say that it was worth it... (and I'm not even close to done with my learning curve).

Phillip H
June 19, 2009

# WPF Productivity

Rick - thats a really interesting comparison - thanks. It reminds me so much of other Microsoft initiatives (like Workflow, SQL Compact etc) where their internal lack of corporate product strategy seems to bleed into their products and wastes a lot of our time. It seems a development team get a good idea, they ship it with a load of marketing and architecture blurb, and see whether it works out or not. If it doesn't work out in the market, or another team get a competing and better product out in the real world, its left to die slowly. Perhaps WPF is like that.... I'm willing to bet that the next release of MS Office isn't based on WPF which maybe shows a lack of depth of committment from the big boys in Redmond.

I personally always wondered what problem WPF was trying to solve. There are libraries for WinForms (my current one being the Telerik user interface library) which make a decent job of making apps look pretty and are good performance. They might even be using DX under the hood for all I know. I realise the idea of a single portable screen definition language, seperating the logic from the layout, and usable in Silverlight and Windows, is a valid idea; but I think they should have chosen one route to get there, not the two Silverlight + WPF differing routes. Even now I believe WPF not to be completely compatible with Silverlight and porting of interface definitions is still a lowest-common-denominator exercise (though I'm happy to be corrected on that point).

Thanks again for your insights.

Joe Gershgorin
June 23, 2009

# re: WPF Bindings and CurrentCulture Formatting

What's the SetCulture method implementation? this.Language can be set at the Window level, but Langauge is an invalid object at the app.xaml.as level. This language have to be set per Window, or can it be set per app?

Joe Gershgorin
June 23, 2009

# re: WPF Bindings and CurrentCulture Formatting

Ah, never mind, ignore the comment above. I should read more carefully, and not at 12:30a.m., ;). The FrameworkElement.LanguageProperty statement above works great, thanks for this timely post! I was about to start converting all my stringformat binding statements to valueconverters (which do adhere to currentculture).

On a related side note, here's a great little tool makes it really easy to test a compiled app under different culture settings.
http://khason.net/blog/how-to-test-localized-application/

Josh
June 26, 2009

# re: WPF Bindings and CurrentCulture Formatting

Even if the next version of office isnt built with WPF, the next version of Visual Studio is being built with it, so there is definitely buy-in from MS into the technology.

Rick Strahl
June 27, 2009

# re: WPF Bindings and CurrentCulture Formatting

@Josh only portions of VS will be built on WPF not the whole thing.

But I think it's also a different story re: developer tools vs. mainstream applications. Blend is all WPF for example. Yet Expression Web (which has a similar *looking* API) is not. It seems to me that MS is very selective of what they try WPF out on <s>...

Pete Maher
October 01, 2009

# re: WPF Bindings and CurrentCulture Formatting

"Hopefully this will help somebody out by making this issue more readily findable."

Yes thanks Rick - First page I went to from Google has saved me considerable time. Forever grateful.

Henrik Hofmann
January 30, 2010

# re: WPF Bindings and CurrentCulture Formatting

Danke, hab ne halbe Stunde rumgesucht bis ich das gefunden habe und gedacht das kann doch nicht wahr sein.

BG
April 21, 2010

# re: WPF Bindings and CurrentCulture Formatting

I am developing a WPF application where we set the current language at start up time based on an enterprise setting. Then, once a user logs in we check the user setting for language and change the current culture if necessary. If another user later logs in, we may need to change the culture yet again. I was using the FrameworkElement.LanguageProperty... to do this, but changing it failed. Finding this post answered that for me, but now I need to come up with a work around.
Anyone have any great ideas? Tks.

Josh Clark
May 04, 2010

# re: WPF Bindings and CurrentCulture Formatting

Thanks Rick for the find with the dateTime & currency format issues. I was digging around your sample on http://wpfguidence.codeplex.com and couldn't find this code on your blog anywhere. After finding your blog and seeing your comment, it all made sense.

Thanks again!

Kim
December 11, 2011

# re: WPF Bindings and CurrentCulture Formatting

Where is your SetCulture(culture); and SetTheme(Theme); method?
What does it do? Have you implemented them yourself or are they implemented in .NET?

Hora
February 19, 2012

# re: WPF Bindings and CurrentCulture Formatting

It doesn't work with WPF Calendar nor DatePicker.

Allen Marshall
November 08, 2013

# re: WPF Bindings and CurrentCulture Formatting

This mechanism may be a bit sticky to use. It matters a whole lot where you invoke this in your application's startup sequence. I found more stability by putting this in a OnStartup event handler viz:

...
...
...
 
 /// <summary>
        /// Event that fires on application startup
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnStartup(object sender, StartupEventArgs e)
        {
            //Uri uri = new Uri("pack://application:,,,/Views/MainWindow.xaml", UriKind.RelativeOrAbsolute);
            //Application.Current.StartupUri = uri;
            try
            {
 
 
                // Ensure the current culture passed into bindings 
                // is the OS culture. By default, WPF uses en-US 
                // as the culture, regardless of the system settings.
                try
                {
                    // per http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.ietflanguagetag(v=vs.110).aspx
 
                    var cultureName = CultureInfo.CurrentCulture.Name;
                    FrameworkElement.LanguageProperty.OverrideMetadata(
                        typeof(FrameworkElement),
                        new FrameworkPropertyMetadata(
                            XmlLanguage.GetLanguage(cultureName)));
                }
                catch (Exception ex)
                {
                    ex.PreserveExceptionDetail();
                    throw;
                }
...
...
...


Also the following use of
IetfLanguageTag 
is deprecated apparently:

this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);


which is why the source snippet above uses:

      var cultureName = CultureInfo.CurrentCulture.Name;


Basically I was getting exceptions on startup because the framework elements (the visual tree?) were not yet instantiated. Dumb, I know, but frustrating. So this is now firing AFTER the app gets going, when the OnStartup event fires, and behaves nicely there.

Here is the main App constructor:
    App()
        {
            // 3) Force just one copy to run
            try
            {
 
                // Setup unhandled exception handlers
                #region Handlers For Unhandled Exceptions
                // anything else to do on startup can go here and will fire after the base startup event of the application
                // First make sure anything after this is handled
                // Creates an instance of the class holding delegate methods that will handle unhandled exceptions.
                CustomExceptionHandler eh = new CustomExceptionHandler();
 
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(eh.OnAppDomainException);
 
                // this ensures that any unhandled exceptions bubble up to a messagebox at least
                Dispatcher.CurrentDispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(eh.OnDispatcherUnhandledException);
 
                #endregion  Handlers For Unhandled Exceptions
 
 
                this.ForceSingleInstance();
 
 
                this.Startup += this.OnStartup;
                this.Exit += this.OnExit;
                this.LoadCompleted += this.OnLoadCompleted;
 
 
                CableStay.Instance.Wire(App.AppDisplayName, false);
 
                this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
 
                InitializeComponent();
 
 
 
            }
            catch (Exception ex)
            {
                ex.PreserveExceptionDetail();
                throw;
            }
        }


You can see that OnStartup is added to the handlers, some other stuff goes on, then InitializeComponent is called. Alternatively this thing can be called after InitializeComponent but ONLY if InitializeComponent() does not work with any FrameworkElement objects, which is highly unlikely.

Nige
August 27, 2014

# re: WPF Bindings and CurrentCulture Formatting

Thanks for this useful post and thanks Allen for the corrections.

I found that, for example if the Resources.resx file contains English texts, there's no need to have a separate Resources.en.resx file. .NET will automatically fall back to the "main" Resources file if the relevant culture-specific file can't be found.

Additionally it seems that although CultureInfo.CurrentCulture is correctly set to the current system culture, Thread.CurrentThread.CurrentUICulture is not. It's this property that determines which resource DLL will be loaded. So to automatically load the correct resources for the current system culture (which is surely the most common scenario) the code should be:

var cultureName = CultureInfo.CurrentCulture.Name;
        
FrameworkElement.LanguageProperty.OverrideMetadata(
   typeof(FrameworkElement),
   new FrameworkPropertyMetadata(
   XmlLanguage.GetLanguage(cultureName)));
 
Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentCulture;

Mallikh
June 20, 2018

# re: WPF Bindings and CurrentCulture Formatting

I am facing the same issue in a WPF application and i tried the solution mentioned here but it is not working. more details here.


Marek Ištvánek
February 26, 2020

# re: WPF Bindings and CurrentCulture Formatting

I hit the problem of CultureInfo.Current(UI)Culture resetting back after my change again in our localization .NET Standard code used in WPF/UWP/... The cultures are changed on main (UI) thread with our SetCulture method, but resetted back after a while by the framework. After adding second call of SetCulture method with UI SynchronizationContext.Post just after the first direct one, cultures are kept and not resetting back occures again. Tested only in WPF.


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024