Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Binding behaviour with Stringformat different than with code?

In some of my projets, I sometime do things like

TxtBox.Text = 10000.ToString("#,0.00") ' TxtBox.Text content = 10 000.00

However, if I have a DataGridTextBoxColumn with binding like this :

{Binding Amount,StringFormat='#,0.00'}

The value shown is 10,000.00 and not 10 000.00

I tried changing both the UI culture and Culture and the application startup but I can only change the way it appears when I use code and not in the binding. Is there any way to make this work ? Is there a 'BindingCulture' of some sort ???

Edit, here is an example of DataGrid I have

<DataGrid x:Name="GridModules" Grid.Column="0" ItemsSource="{Binding}" Style="{StaticResource BaseGrid}" IsTabStop="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Nom" Width="*"  MinWidth="150"
                                               Binding="{Binding Nom}"                                               
                                               IsReadOnly="True" />
        <DataGridTextColumn Header="Prix" Width="120"  MinWidth="100"
                                               Binding="{Binding PrixAvantTaxe, StringFormat='#,0.00'}"
                                               CellStyle="{StaticResource RightCellStyle}"
                                               IsReadOnly="True" />
        <DataGridCheckBoxColumn Header="Révisé" Width="100"  MinWidth="100"
                                                Binding="{Binding EstRevise}"                                                      
                                                IsReadOnly="True" />
    </DataGrid.Columns>
</DataGrid>

Edit : I think my question is misunderstood. I would like to get 10 000.00, which is what I get when I use code and NOT 10,000.00, which is what I get when I use binding in datagrids.

like image 751
David Brunelle Avatar asked May 12 '26 06:05

David Brunelle


1 Answers

Ok it seems that this amounts to pretty much a formatting question. If you know a specific Culture which uses teh space character as it's NumberGroupSeparator You could use that culture; otherwise, the following example ripped right from the msdn link provided should help:

   public static void Main() {

      // Gets a NumberFormatInfo associated with the en-US culture.
      NumberFormatInfo nfi = new CultureInfo( "en-US", false ).NumberFormat;

      // Displays a value with the default separator (",").
      Int64 myInt = 123456789;
      Console.WriteLine( myInt.ToString( "N", nfi ) );

      // Displays the same value with a blank as the separator.
      nfi.NumberGroupSeparator = " ";
      Console.WriteLine( myInt.ToString( "N", nfi ) );

   }

You can do something like the above in an IValueConverter and you can then specify the original format you provided.

Edit This should work.

public class NumberFormatConverter: IValueConverter {        
    public string GroupSeperator { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value == null) return DependencyProperty.UnsetValue;
        var type = value.GetType();
        var stringFormat = parameter as string;
        if (IsNumeric(type)) {
            if (stringFormat == null) {
                return value.ToString();
            }
            var formattible = (IFormattable)value;
            // Gets a NumberFormatInfo associated with the en-US culture.
            NumberFormatInfo nfi;
            if (GroupSeperator == null) {
                nfi = culture.NumberFormat;
            } else {
                nfi = ((CultureInfo) culture.Clone()).NumberFormat;
                nfi.NumberGroupSeparator = GroupSeperator;                
            }
            return formattible.ToString(stringFormat, nfi);
        }
        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return DependencyProperty.UnsetValue;
    }

    public static bool IsNumeric(Type type) {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) {
            var elementType = new NullableConverter(type).UnderlyingType;
            return IsNumeric(elementType);
        }
        return
            type == typeof(Int16) ||
            type == typeof(Int32) ||
            type == typeof(Int64) ||
            type == typeof(UInt16) ||
            type == typeof(UInt32) ||
            type == typeof(UInt64) ||
            type == typeof(decimal) ||
            type == typeof(float) ||
            type == typeof(double);
    }
}

And the XAML:

    <DataGrid x:Name="Accounts" ItemsSource="{Binding Accounts}" AutoGenerateColumns="False" AlternatingRowBackground="Azure">
        <DataGrid.Resources>
            <local:NumberFormatConverter x:Key="NumberFormatConverter" GroupSeperator=" " />
            <local:NumberFormatConverter x:Key="UnderScoreNumberFormatConverter" GroupSeperator="_" />
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
            <DataGridTextColumn Header="Amount" Binding="{Binding Amount, Converter={StaticResource NumberFormatConverter},ConverterParameter='#,0.00'}" />
            <DataGridTextColumn Header="Whole Dollars" Binding="{Binding WholeDollars, Converter={StaticResource UnderScoreNumberFormatConverter},ConverterParameter='#,0.00'}" />
        </DataGrid.Columns>
    </DataGrid>
like image 113
Damian Avatar answered May 14 '26 20:05

Damian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!