3

I am using two different currencies in my software. Depending on company origin how can I show the currency before numerical data. Either £ or €

<TextBlock Text="{Binding FNetPriceAfterDisc,StringFormat=c}"  />

I would like to Bind "c" in code behind. If possible.

I tried this but doesn't work. Not sure what's wrong.

                                     <TextBlock  HorizontalAlignment="Center" >
                                    <TextBlock.Style>
                                        <Style TargetType="TextBlock">
                                            <Setter Property="Text" Value="{Binding FNetPriceAfterDisc,StringFormat=€0.000}" />
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding Country}" Value="UK">
                                                    <Setter Property="Text" Value="{Binding FNetPriceAfterDisc,StringFormat=c}" />
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </TextBlock.Style>
                                </TextBlock>
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
AliAzra
  • 889
  • 1
  • 9
  • 28
  • You can use some kind of data-trigger in WPF. for example look at this https://www.wpf-tutorial.com/styles/trigger-datatrigger-event-trigger/ – Anirudha Gupta Aug 23 '19 at 15:06
  • try this : https://stackoverflow.com/questions/34237911/currency-symbol-in-numeric-value-based-on-object-property-in-xaml – Jophy job Aug 23 '19 at 15:20

2 Answers2

3

I'd give each item a language identifier tag as a string: en-GB, de, en-US, etc. I'd then write a MultiValueConverter and use that to format arbitrary text, with an arbitrary format, for an arbitrary culture. Since the format string to specify "currency" is also a parameter, this can be used for other localization tasks. It's important not simply to hardcode currency symbols: If Italy leaves the Eurozone, you shouldn't have to lose sleep over it (unless the EU pays your salary).

public class CultureFormatConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, 
        CultureInfo culture)
    {
        var value = values[0];
        var format = values[1] as String;
        var targetCulture = values[2] as string;

        return string.Format(new System.Globalization.CultureInfo(targetCulture), 
            format, value);
    }

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

Create the converter in Resources somewhere where it'll be in scope:

<local:CultureFormatConverter x:Key="CultureFormatConverter" />

And then use it like so:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource CultureFormatConverter}">
            <!-- Bind to FNetPriceAfterDisc property of the viewmodel -->
            <Binding Path="FNetPriceAfterDisc" />

            <!-- To pass a literal value with a binding, assign it to Source -->
            <Binding Source="{}{0:c}" />

            <!-- 
            Bind to Culture property of the viewmodel: Should be String that returns 
            "de" for Germany, "en-GB" for UK, null for Pennsylvania and Australia. 
            If you want a fixed value, make it Source="de" or whatever, not Path="de".
            But if you want to use a constant culture value, you might be happier 
            just using the ConverterCulture parameter to an ordinary binding. 
            -->
            <Binding Path="Culture" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>
  • Thank you Ed. I set but var targetCulture = values[2] as string; retruns null all the time. no matter what i set it always returns null – AliAzra Aug 23 '19 at 15:46
  • Look how I did the literal value for the format: `Source="{}{0:c}"`. Source for a literal value, not Path. Where's the `de` property on your viewmodel? There isn't one. Why did you think `de` would make sense as a Path? – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 15:52
  • The point here is that you want to **bind** the culture, so it can vary according to the data you're displaying. It has to be a binding, and setting a literal value by a Binding works this way. – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 15:53
  • Sorry but i am new to this binding. I don't understand. Some companies in the UK others in Europe. I want to show the currency depending on which country selected. Above code always shows £. How can i to change the currency to Euro when selected comapny Counry = "EURO". I thought i am sending 3 variables to to IMultiValueConverter and with if condition if it is UK use en-GB, if it is Euro use de – AliAzra Aug 23 '19 at 16:02
  • `FNetPriceAfterDisc` is a property of something. A class. What is the class it is a property of? – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 16:03
  • Yes it is a price property. public decimal FNetPriceAfterDisc { get; set; } – AliAzra Aug 23 '19 at 16:05
  • I know it is a property. Can you find out the name of the class where it is defined, and tell me the name of the class? – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 16:08
  • public class ManualExcelPrintData { public string PriceGroup { get; set; } public string ProductCode { get; set; } public decimal FNetPriceAfterDisc { get; set; } public decimal GRRP { get; set; } public decimal FRetroRecovery { get; set; } public decimal FSubsidy { get; set; } } – AliAzra Aug 23 '19 at 16:11
  • The name of the class is `public class ManualExcelPrintData { public string PriceGroup { get; set; } public string ProductCode { get; set; } public decimal FNetPriceAfterDisc { get; set; } public decimal GRRP { get; set; } public decimal FRetroRecovery { get; set; } public decimal FSubsidy { get; set; } } `. Thank you. Give that class a new property which is a string called `Culture` which has the culture for the customer: If the customer is German, `Culture` should be return `"de"`. If the customer is English, `Culture` should return `"en-GB"`. – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 16:14
  • Now it makes sense. Thank you. This is my first WPF application. I am a web developer and this binding is quite complicated... Thanks a lot. – AliAzra Aug 23 '19 at 16:21
  • 1
    @AliAzra There's a lot to learn with WPF, that's for sure. – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 16:23
  • @AliAzra I added comments in the XAML to clarify usage. – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 16:27
  • 1
    **Trolling** It is generally bad idea to pass whole default culture info to just get currency formatting - imaging you have USD and EUR - so you show something like "1,00$ + 1.00€" - roughly how much it is (~$101, $2.11, $112, $211)? If you really care you need to construct formatter from currency symbol(for that currency), currency format pattern (your call either current culture or currency's one) and numeric format (current culture)… **End of trolling** – Alexei Levenkov Aug 23 '19 at 17:00
  • @AlexeiLevenkov That's a fair point. – 15ee8f99-57ff-4f92-890c-b56153 Aug 23 '19 at 17:06
0

You could either implement the IFormattable interface on the parent class, or define a IValueConverter' and using asConverterParameter` the company origin.

Or, if you have already the currency type as a property in your bound object, you could use a MultiBinding :

  <TextBlock>
    <TextBlock.Text>
      <MultiBinding  StringFormat="{}{0} {1}">
        <Binding Path="FNetPriceAfterDisc"/>
        <Binding Path="CompanyCurrency"/>
      </MultiBinding>
    </TextBlock.Text>
  </TextBlock>

EDIT: Old line was:

      <MultiBinding  StringFormat="{0} {1}">

Correct line is

      <MultiBinding  StringFormat="{}{0} {1}">
marcodt89
  • 371
  • 1
  • 6