Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two way percentage formatted binding in WPF

I have this textbox:

<TextBox Text="{Binding Path=TaxFactor, StringFormat=P}" />

It correctly displays 0.05 as 5%, but it doesn't work going back. When I type in a percentage, it fails because of the percent symbol. If I try writing just a number, like 5, I get 500% instead. I have to write 0.05 for it to work.

Do I have to write a custom converter to get my percentage back? And if so, how do I get around locale-specific percentage formats?

like image 748
Alex J Avatar asked Feb 11 '11 11:02

Alex J


2 Answers

You need to write a custom converter. NOTE: this one assumes that the values are stored in the range 0 to 100 rather than 0 to 1.

public object Convert(object value, Type targetType, object parameter,
                      System.Globalization.CultureInfo culture)
{
    if (string.IsNullOrEmpty(value.ToString())) return 0;

    if (value.GetType() == typeof(double)) return (double)value / 100;

    if (value.GetType() == typeof(decimal)) return (decimal)value / 100;    

    return value;
}

public object ConvertBack(object value, Type targetType, object parameter,
                          System.Globalization.CultureInfo culture)
{
    if (string.IsNullOrEmpty(value.ToString())) return 0;

    var trimmedValue = value.ToString().TrimEnd(new char[] { '%' });

    if (targetType == typeof(double))
    {
        double result;
        if (double.TryParse(trimmedValue, out result))
            return result;
        else
            return value;
    }

    if (targetType == typeof(decimal))
    {
        decimal result;
        if (decimal.TryParse(trimmedValue, out result))
            return result;
        else
            return value;
    }
    return value;
}

The call it like this:

<TextBox Text="{Binding Path=TaxFactor, Mode=TwoWay, StringFormat=P, 
         Converter={StaticResource percentStringFormatConverter} />

this is from some Silverlight code, but should work with WPF

like image 197
ChrisF Avatar answered Nov 02 '22 05:11

ChrisF


Adding to ChrisF's answer, the converter I ended up using (only for decimals):

class DecimalPercentageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                  System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
                              System.Globalization.CultureInfo culture)
    {
        if (targetType != typeof(decimal) || value == null)
            return value;

        string str = value.ToString();

        if (String.IsNullOrWhiteSpace(str))
            return 0M;

        str = str.TrimEnd(culture.NumberFormat.PercentSymbol.ToCharArray());

        decimal result = 0M;
        if (decimal.TryParse(str, out result)) {
            result /= 100;
        }

        return result;
    }
}
like image 6
Alex J Avatar answered Nov 02 '22 04:11

Alex J