WPF使用Stringformat与代码绑定的行为不同吗?

3

在我的一些项目中,我有时会做以下事情:

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

然而,如果我有一个绑定如下的DataGridTextBoxColumn:
{Binding Amount,StringFormat='#,0.00'}

显示的值是10,000.00而不是10 000.00。

我尝试更改UI文化和Culture以及应用程序启动,但只能在使用代码时更改其外观,而不能在绑定中更改。是否有办法使此工作?是否有某种“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。


你试过了吗?{Binding Amount,StringFormat={}{0:#,0.00}} - Damian
这本身不会编译,因为有逗号,但我会尝试用''并给你结果。 - David Brunelle
即使加上 '' 也没有任何区别。 - David Brunelle
什么是RightCellStyle?这很可能是导致您问题的原因。您可能正在寻找ElementStyle和EditingElementStyle。 - Damian
它确实起作用,但如果我想要超过一个空格,我需要放置### ### ### #0.00,这在这种情况下可以接受,但我不太喜欢它,因为我不明白为什么其他方法不起作用。 - David Brunelle
3个回答

1

好的,看起来这基本上是一个格式化问题。如果您知道使用空格作为其 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
从下面这个试验(它是有效的)可以清楚地看出,问题不在于绑定,而是与网格列的显示方式有关。您能否插入一段您的网格定义代码(我主要想知道值绑定到哪种类型的列)? 编辑 现在假设像下面这样定义,这对我有效。这里还有其他因素在起作用。
<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


0

对我来说,两者都可以正常工作,显示为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,或者设置您的Label的ContentStringFormat以应用格式。

正如您所指出的,ContentControls 需要设置 ContentStringFormat 而不是 StringFormat。 - Damian
重点是它不应该显示10,000.00,而应该显示10 000.00,但当我“编写格式”时它确实这样做。 - David Brunelle
@DavidBrunelle 对我来说,#,0.00 格式化为 10,000.00,即使使用 ToString() 版本也是如此。要删除逗号,请从 StringFormat 中删除逗号。 - Rachel
尝试使用StringFormat='# ##0.00'(我假设您想要那个空格)。 - Damian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接