1

In App.xaml.cs I have:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

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

In my MainWindow.xaml.cs I have:

NumberFormatInfo nfi = System.Threading.Thread.CurrentThread
                       .CurrentCulture.NumberFormat;
nfi.CurrencySymbol = "USD";
nfi.CurrencyDecimalSeparator = ".";
nfi.CurrencyDecimalDigits = 0;

NumberFormatInfo nfi = System.Threading.Thread.CurrentThread
                       .CurrentUICulture.NumberFormat;
nfi.CurrencySymbol = "USD";
nfi.CurrencyDecimalSeparator = ".";
nfi.CurrencyDecimalDigits = 0;

Now in a different window, which will be opened from the MainWindow, I wrote the following:

<TextBox Text="{Binding Total, StringFormat=c}"

But the result is something like $1,200.00, not what I expected: USD1,200. What's wrong here?

synergetic
  • 7,756
  • 8
  • 65
  • 106

2 Answers2

2

There might be smarter ways, but this should work consistently...

// xmlns:sysglb="clr-namespace:System.Globalization;assembly=mscorlib"
<TextBox Text="{Binding Total, StringFormat='{}{0:C}', ConverterCulture={x:Static sysglb:CultureInfo.CurrentUICulture}}" />  

And move this at app startup or ctor...

Then do the OverrideMetadata and before base.OnStartup - e.g...

protected override void OnStartup(StartupEventArgs e)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");

    NumberFormatInfo nfi = System.Threading.Thread.CurrentThread
                            .CurrentCulture.NumberFormat;
    nfi.CurrencySymbol = "USD";
    nfi.CurrencyDecimalSeparator = ".";
    nfi.CurrencyDecimalDigits = 0;

    nfi = System.Threading.Thread.CurrentThread
                            .CurrentUICulture.NumberFormat;
    nfi.CurrencySymbol = "USD";
    nfi.CurrencyDecimalSeparator = ".";
    nfi.CurrencyDecimalDigits = 0;

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

    base.OnStartup(e);

}

See also:

WPF StringFormat={0:C} showing as dollars

Community
  • 1
  • 1
NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51
  • Your code could work, but what I'm trying to achieve is dynamically change NumberFormat when a culture-specific database is opened. Your code requires to restart the app again. – synergetic Apr 12 '13 at 00:33
0

NumberFormatting is an operation that uses your CurrentCulture (by default unless you explicitly provide a Culture or NumberFormatter to the method) NOT CurrentUICulture. CurrentUICulture is used for resource (localization) lookup.

The NumberFormatInfo you get from the CurrentCulture should be read only (see Remarks of NumberFormatInfo documentation) and should throw an InvalidOperationException when you attempt to set any of the properties (see Remarks of NumberFormatinfo.IsReadOnly). (Are you swallowing this exception?) If you create a writable CultureInfo and change its properties, you can then set that as your current culture.

You need to do something like:

CultureInfo ci = CultureInfo.CreateSpecificCulture("en-US");
NumberFormatInfo nfi= ci.NumberFormat;
nfi.CurrencySymbol = "USD";
nfi.CurrencyDecimalSeparator = ".";
nfi.CurrencyDecimalDigits = 0;
// set the default culture for all threads that haven't been explicitly set (.Net 4.5)
CultureInfo.DefaultThreadCurrentCulture = ci;
// or the following if you aren't using .Net 4.5
// Thread.CurrentThread.CurrentCulture = ci;
Bart Calixto
  • 19,210
  • 11
  • 78
  • 114
Eric MSFT
  • 3,246
  • 1
  • 18
  • 28
  • 1
    I checked; nfi.IsReadOnly equals to false. The code works; CurrencyDecimalDigits becomes from 2 to 0. I also copy/pasted your code, but nothing changed. – synergetic Apr 12 '13 at 00:27