Поведение привязки WPF с Stringformat отличается от кода? - PullRequest
3 голосов
/ 01 декабря 2011

В некоторых моих проектах я иногда делаю что-то вроде

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

Однако, если у меня есть DataGridTextBoxColumn с привязкой, как это:

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

Показанное значение равно 10 000,00, а не 10 000,00

Я пытался изменить как культуру пользовательского интерфейса, так и Культуру и запуск приложения, но я могу изменить только то, как он отображается, когда я использую код, а не в привязке. Есть ли способ сделать эту работу? Существует ли какая-нибудь «BindingCulture» ???

Редактировать, вот пример DataGrid, который у меня есть

<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>

Редактировать: я думаю, что мой вопрос неправильно понят. Я хотел бы получить 10 000,00, то есть то, что я получаю, когда использую код, а НЕ 10 000,00, то есть то, что я получаю, когда использую связывание в сетях данных.

Ответы [ 3 ]

1 голос
/ 01 декабря 2011

Хорошо, похоже, это в значительной степени вопрос форматирования. Если вы знаете конкретную культуру, которая использует символ пробела, так как это NumberGroupSeparator Вы можете использовать эту культуру; в противном случае следующий пример, извлеченный прямо из предоставленной ссылки msdn, должен помочь:

   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 ) );

   }

Вы можете сделать что-то подобное выше в IValueConverter, а затем указать исходный формат, который вы указали.

Редактировать Это должно работать.

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);
    }
}

И 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>
0 голосов
/ 01 декабря 2011

Оба работают нормально для меня, показывая 10,000.00

TestText.Text = 10000.ToString("#,0.00")

<DataGrid ItemsSource="{Binding Test}">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding TestNumber,StringFormat={}{0:#\,0.00}}" Header="Test1" />
        <DataGridTextColumn Binding="{Binding TestNumber,StringFormat='#,0.00'}" Header="Test2" />
    </DataGrid.Columns>
</DataGrid>

Я подозреваю, что проблема связана с Label где-то.Метки WPF имеют свойство ContentStringFormat, которое переопределяет любые StringFormat в привязке.

Например,

<TextBlock x:Name="ThisWorks" 
           Text="{Binding TestNumber,StringFormat={}{0:#\,0.00}}" />

<Label x:Name="DoesNotWork" 
           Text="{Binding TestNumber,StringFormat={}{0:#\,0.00}}" />

<Label x:Name="Works" 
           Content="{Binding TestNumber}" 
           ContentStringFormat="#,0.00" />

Я бы предложил загрузить Snoop и посмотреть, так ли это.Если это так, переключите Labels на TextBlocks или настройте ContentStringFormat вашего ярлыка для применения форматирования

0 голосов
/ 01 декабря 2011

Из этого примера ниже (который работает) ясно, что это не привязка, а что-то с тем, как отображается столбец сетки. Не могли бы вы вставить фрагмент определения сетки (меня интересует, к какому типу столбца относится значение)?

Редактировать Теперь при условии определения, как ниже, это работает для меня. Здесь есть что-то еще.

<DataGrid x:Name="Accounts" ItemsSource="{Binding Accounts}" AutoGenerateColumns="False" AlternatingRowBackground="Azure">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
        <DataGridTextColumn Header="Amount" Binding="{Binding Amount, StringFormat='# ##0.00'}" />
        <DataGridTextColumn Header="Whole Dollars" Binding="{Binding WholeDollars, StringFormat='# ##0.00'}" />
    </DataGrid.Columns>
</DataGrid>

Редактировать Теперь, когда вы показали свое определение, я уверен, что это ваш CellStyle, который нарушает это. Что такое RightCellStyle? Вы использовали ElementStyle или EditingElementStyle ?

...