Search code examples
c#wpfxamlglobalization

Setting global NumberDecimalSeperator / Culture - WPF XAML


I have a really, really small problem that seems unsolveable in WPF. I need a custom NumberFormatInfo and DateFormatInfo for my app and don't want to make use of StringFormat option in XAML every time I am using a number or a date.

So I tried to globalize it globally like this:

    private void SetCulture()
    {

        var cultureInfo = CultureInfo.CurrentCulture;

        if (!string.IsNullOrEmpty(Settings.Default.LanguageOverride))
            cultureInfo = new CultureInfo(Settings.Default.LanguageOverride);

        cultureInfo.NumberFormat.NumberDecimalDigits = 2;
        cultureInfo.NumberFormat.NumberDecimalSeparator = ",";
        cultureInfo.NumberFormat.NumberGroupSeparator = ".";


        cultureInfo.DateTimeFormat.ShortDatePattern = "dd.MM.yyyy";
        cultureInfo.DateTimeFormat.FullDateTimePattern = "dd.MM.yyyy";
        cultureInfo.DateTimeFormat.ShortTimePattern = "HH:mm";
        cultureInfo.DateTimeFormat.LongDatePattern = "dd.MM.yyyy";
        cultureInfo.DateTimeFormat.LongTimePattern = "HH:mm";


        SetCulture(cultureInfo);
    }

    private void SetCulture(CultureInfo cultureInfo)
    {
        LocalizeDictionary.Instance.IncludeInvariantCulture = false;

        CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
        CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

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

        LocalizeDictionary.Instance.Culture = cultureInfo;

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

This isn't working. DateTime and Decimal values on my gui are not effected, regardless what I'm doing.

I got it to work with CultureAndRegionInfoBuilder but it needs administrative privileges. That's not what I want.

Any suggestions? Thanks


Solution

  • You can only set the FrameworkElement.Language property to a language, but not to a custom CultureInfo. CultureInfo.CurrentCulture.IetfLanguageTag returns a language tag that is not affected by NumberFormat or DateTimeFormat properties of CultureInfo.CurrentCulture.

    What you could to do apply the formatting globally is to define a custom binding where you set the ConverterCulture property in one place:

    public class CustomBinding : Binding
    {
        private static readonly CultureInfo cultureInfo;
        static CustomBinding()
        {
            cultureInfo = new CultureInfo("sv");
    
            cultureInfo.NumberFormat.NumberDecimalDigits = 2;
            cultureInfo.NumberFormat.NumberDecimalSeparator = ",";
            cultureInfo.NumberFormat.NumberGroupSeparator = ".";
    
            cultureInfo.DateTimeFormat.ShortDatePattern = "dd.MM.yyyy";
            cultureInfo.DateTimeFormat.FullDateTimePattern = "dd.MM.yyyy";
            cultureInfo.DateTimeFormat.ShortTimePattern = "HH:mm";
            cultureInfo.DateTimeFormat.LongDatePattern = "dd.MM.yyyy";
            cultureInfo.DateTimeFormat.LongTimePattern = "HH:mm";
        }
    
        public CustomBinding()
        {
            ConverterCulture = cultureInfo;
        }
    
        public CustomBinding(string path)
            : base(path)
        {
            ConverterCulture = cultureInfo;
        }
    }
    

    You could then replace all your current bindings with your custom markup extension, e.g.:

    <TextBlock Text="{local:CustomBinding Date}" />