Currency symbol in numeric value based on object property in XAML

时光怂恿深爱的人放手 提交于 2019-12-12 18:44:55

问题


How to show a numeric (currency) value in WPF so that the currency symbol would not come from the user's regional settings, locale or anything but from the property of the binded object.

For example in DataGrid I would have Item objects:

 <DataGrid Grid.Row="1" ItemsSource="{Binding Items}">
      <DataGrid.Columns>
           <DataGridTextColumn Binding="{Binding SomeNumber, StringFormat=c}" />
      </DataGrid.Columns>
 </DataGrid>

public Item()
{
    public double SomeNumber { get; set; }
    public string CurrencySymbol { get; set; }
}

The above standard "c"formatting will show currency symbol based on some user setting and ignoring the business object.

But the value should be displayed like this

SomeNumber = 3456234.67 (positive numbers)

CurrencySymbol ="€" > €3 456 234.67
CurrencySymbol ="$" > $3 456 234.67
CurrencySymbol ="₽" > ₽3 456 234.67

SomeNumber = -3456234.67 (negative numbers)

CurrencySymbol ="€" > (€3 456 234.67)
CurrencySymbol ="$" > ($3 456 234.67)
CurrencySymbol ="₽" > (₽3 456 234.67)

SomeNumber= 0 (zero values)

CurrencySymbol ="€" > -
CurrencySymbol ="$" > -
CurrencySymbol ="₽" > -

Is there a way to get the currency symbol to the value this way with StringFormat?


回答1:


The correct way to automatically attach the currency symbol to a number using StringFormat is by using a ConverterCulture:

<!-- This will be shown as '¥1,423.7' -->
<DataGridTextColumn Header="Amount"
                    Binding="{Binding Path=SomeNumber,
                                      StringFormat=c,
                                      ConverterCulture='ja-JP'}"/>

<!-- This will be shown as '1.423.70 €' -->
<DataGridTextColumn Header="Amount"
                    Binding="{Binding Path=SomeNumber,
                                      StringFormat=c,
                                      ConverterCulture='de-DE'}"/>

The good thing about it is that the number is also formatted according to requested ConverterCulture.

In your case you want to format the number yourself (notice the position of the currency symbol is changing according to the ConverterCulture as well), also, you want to decide what will be the currency displayed yourself, which makes it impossible to relay on the ConverterCulture.

In this case, the correct way to do it will be creating an IValueConverter yourself:

public class CurrencyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Item valueAsItem = value as Item;
        if (valueAsItem != null)
        {
            double amount = valueAsItem.SomeNumber;
            if (amount == 0)
            {
                return "-"; //In the question this is the display for 0.
            }
            if (amount < 0)
            {
                amount *= -1; //In the question the numbers always display positive.
            }
            //In the question this is the format for the numbers.
            return valueAsItem.CurrencySymbol + amount.ToString("### ### ###.###");
        }
        return string.Empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

And in the .xaml:

  • Inside the Window Attribute:

    <Window.Resources>
        <local:CurrencyConverter 
      x:Key="CurrencyConverter" />
    </Window.Resources>
    
  • And for the DataGrid:

    <DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Amount"
                                Binding="{Binding Converter={StaticResource CurrencyConverter}}"/>
            </DataGrid.Columns>
    </DataGrid>
    

Now when the DataContext is as the following:

public class MyDataContext
{
    public ICollectionView MyItems { get; set; }

    public MyDataContext()
    {
        List<Item> items = new List<Item>
        {
            new Item { CurrencySymbol = "$", SomeNumber = 123.4 },
            new Item { CurrencySymbol = "₹", SomeNumber = 0 },
            new Item { CurrencySymbol = "₹", SomeNumber = -14345623.7 }
        };

        MyItems = CollectionViewSource.GetDefaultView(items);
    }
}

public class Item
{
    public double SomeNumber { get; set; }
    public string CurrencySymbol { get; set; }
}

The grid looks like that:

as requested.

More info on double formatting on MSDN.



来源:https://stackoverflow.com/questions/34237911/currency-symbol-in-numeric-value-based-on-object-property-in-xaml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!