WPF中的双向百分比格式绑定

8

我有一个文本框:

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

它可以正确地将0.05显示为5%,但在返回时却无法正常工作。当我输入百分数时,它会因为百分号而失败。如果我尝试只写一个数字,比如5,那么我会得到500%。我必须写0.05才能使其正常工作。
我需要编写自定义转换器才能获取我的百分比吗?如果是这样,那么我该如何解决特定于区域设置的百分比格式问题?
2个回答

11

您需要编写一个自定义转换器。注意:此代码假设值存储在0到100的范围内,而不是0到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;
}

调用方法如下:

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

这段代码来自某些 Silverlight 代码,但应该适用于 WPF


1
对于我目前的需求来说已经足够了,尽管转换器需要进行一些微调(它没有将数字除以100),并且忽略了本地化。谢谢。 - Alex J
@Ilia - 啊,我们将百分比存储为0到100的数字(别问我为什么),而不是0到1。至于本地化 - 它应该可以处理 - 我需要在我们的应用程序上再次检查一下(感谢您的提醒)。 - ChrisF
我已经将我满意的代码作为另一个答案发布了。我猜我可以使用 culture.NumberFormat.Percent* 值进行更准确的解析,但这对我来说已经足够好了。 - Alex J
WPF的ProgressBar类使用0到100的范围。也许这就是为什么你的代码库使用0到1之间的范围。 - sourcenouveau
@emddudley - 我们实际上正在编写一款 Silverlight 应用程序 :) 另外,数字并不在进度条上。但除此之外,这是一个好主意 ;) - ChrisF

6

在ChrisF的回答基础上,我最终使用的转换器(仅适用于小数):

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

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