Assorted settings in the Windows 7 Region and Language dialog supply values to the properties of the CurrentCulture object. However, WPF controls seem to use CurrentUICultur
There is one very dirty way to do it in WPF, but as far as I could find it is the best, because it works without any other extra code or having specific culture aware bindings. The only thing you have to do is call SetFrameworkElementLanguageDirty method (below in the answer) in your application startup or even better in constructor of the App.
The method comments are self-explanatory, but in short the method overrides the default metadata of LanguageProperty of FrameworkElement with CurrentCulture including user's specific modification from windows, if there are any. The downsize/dirty part is that it is using reflection to set a private field of XmlLanguage object.
/// <summary>
/// Sets the default language for all FrameworkElements in the application to the user's system's culture (rather than
/// the default "en-US").
/// The WPF binding will use that default language when converting types to their string representations (DateTime,
/// decimal...).
/// </summary>
public static void SetFrameworkElementLanguageDirty()
{
// Note that the language you get from "XmlLanguage.GetLanguage(currentCulture.IetfLanguageTag)"
// doesn't include specific user customizations, for example of date and time formats (Windows date and time settings).
var xmlLanguage = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.IetfLanguageTag);
SetPrivateField(xmlLanguage, "_equivalentCulture", Thread.CurrentThread.CurrentCulture);
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(xmlLanguage));
}
The SetPrivateField method can look like this.
private static void SetPrivateField(object obj, string name, object value)
{
var privateField = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
if (privateField == null) throw new ArgumentException($"{obj.GetType()} doesn't have a private field called '{name}'.");
privateField.SetValue(obj, value);
}
This SO post (WPF/Silverlight) has a link to this article (WPF only), explaining how to use CurrentCulture as the default for your application. Does that solve your problem?
EDIT:
Making bindings use the custom settings from "Region and Language" instead of the current language's default settings requires some more trickery. This post concludes that every binding's ConverterCulture
also has to be explicitly set to CultureInfo.CurrentCulture
. Here are some DateTime tests:
<!-- Culture-aware(?) bindings -->
<StackPanel DataContext="{Binding Source={x:Static sys:DateTime.Now}}" >
<!-- WPF's default en-US formatting (regardless of any culture/language settings) -->
<TextBlock Text="{Binding Path=.}" />
<!-- *Default* norwegian settings (dd.MM.YYY) -->
<TextBlock Text="{Binding Path=., ConverterCulture=nb-NO}" />
<!-- Norwegian settings from the "Region and Languague" dialog (d.M.YY) -->
<TextBlock Text="{Binding Path=., ConverterCulture={x:Static sysglb:CultureInfo.CurrentCulture}}" />
<!-- Hiding ConverterCulture initialization in our own custom Binding class as suggested here:
https://stackoverflow.com/questions/5831455/use-real-cultureinfo-currentculture-in-wpf-binding-not-cultureinfo-from-ietfl#5937477 -->
<TextBlock Text="{local:CultureAwareBinding Path=.}" />
</StackPanel>
The custom binding class:
public class CultureAwareBinding : Binding
{
public CultureAwareBinding()
{
this.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;
}
}
It all ends up looking like this on a norwegian machine: