小数分隔符取决于当前文化

问题描述 投票:0回答:1

在我的 .NET MAUI 应用程序中,我可以在内部切换文化。根据这一点,我想更改小数点分隔符。在条目中,我使用了一个例程,只允许在 TextChanged-Event 上使用正确的小数分隔符,以便用户可以插入正确的格式,我支持。到目前为止,这有效:

public class DecimalSeparatorValidator
{
    private CultureInfo culture;

    public DecimalSeparatorValidator(CultureInfo culture)
    {
        this.culture = culture ?? throw new ArgumentNullException(nameof(culture));
    }

    public string ValidateAndReplaceDecimalSeparator(string input)
    {
        if (input == null)
        {
            throw new ArgumentNullException(nameof(input));
        }

        // Replace the wrong decimal separator
        var numberDecimalSeparator = culture.NumberFormat.NumberDecimalSeparator;
        var correctedInput = input.Replace(numberDecimalSeparator == "." ? "," : ".", numberDecimalSeparator);

        // Validate the input format with regex
        var match = Regex.Match(correctedInput, "^(0|0[.,][0-9]*|[1-9]+[.,]*[0-9]*)$");
        if (!match.Success)
        {
            // If the input does not match the desired format, return null
            return null;
        }

        return correctedInput;
    }
}

在 XAML 中,我附加了以下 StringToDoubleConverter 来解析双精度:

Text="{Binding Item.Value, Converter={StaticResource StringToDoubleConverter}, Mode=TwoWay}"
public class StringToDoubleConverter : IValueConverter
{
    // Used when the Double Value is converted to the String
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    // Used when the String value from the Entry is converted back to the Double
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string stringValue)
        {
            char decimalSeparator = GetDecimalSeparator(stringValue);
            stringValue = stringValue.Replace(decimalSeparator, CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator[0]);

            if (double.TryParse(stringValue, out double result))
            {
                return result;
            }
        }

        return 0.0; // Default value or handle error accordingly
    }

    private static char GetDecimalSeparator(string input)
    {
        foreach (char character in input)
        {
            if (!char.IsDigit(character))
            {
                return character;
            }
        }

        return '.';
    }
}

不幸的是,当我在内部切换文化时,不再调用它,并且视图中的小数分隔符保持不变。

我想要实现的是,在相应的文化中,有一个“.”。用作小数分隔符,当用户键入“3.14”时使用,当使用“,”时,它显示为“3,14”。

当我在内部改变文化时,有没有办法可以触发这一点?

maui culture
1个回答
0
投票

我想指出 TryParse 重载之一采用

IFormatProvider
(请参阅 https://learn.microsoft.com/en-us/dotnet/api/system.double.tryparse?view=net-8.0#系统双tryparse(系统字符串系统-iformatprovider-系统双@)):

public static bool TryParse (string? s, IFormatProvider? provider, out double result);

您应该使用此重载并删除您的

string.Replace logic
:

double.TryParse(stringValue, CultureInfo.CurrentCulture, out double result))

关于您的绑定问题,您可以用来应对文化变化的技巧之一是使用

MultiBinding
并将文化作为依赖绑定之一。这是您
MultiBinding
中的虚拟对象,因为我们将其用作触发器,所以我们没有使用它的值:

<Label.Text>
    <MultiBinding Converter="{StaticResource StringToDoubleConverter}">
        <Binding Path="Item.Value"/>
        <Binding Path="NumberCulture"/>
    <MultiBinding>
</LabelText>

这需要您将

StringToDoubleConverter
IValueConverter
更改为
IMultiValueConverter
,但是,您只需获取给定数组的第一个值并按照当前的操作进行转换即可。

至于第二个参数,它是您使用

OnPropertyChanged
系统向所有知道您已更改的数字的组件广播的一种方式
CultureInfo.CurrentCulture
。例如

public CultureInfo NumberCulture => CultureInfo.CurrentCulture;

public void ChangeNumberCulture(CultureInfo NewCultureInfo)
{
    CultureInfo.CurrentCulture = NewCultureInfo;
    OnPropertyChanged(nameof(NumberCulture)); // broadcast to all MultiBindings a change in number culture has occurred.
}

我建议始终显示

Label
,并且通过手势,说单击以更改
Entry
字段的可见性,因此,大多数时候,只需要有一个 OneWay 绑定即可反映数字格式改变。

© www.soinside.com 2019 - 2024. All rights reserved.