在我的 .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”。
当我在内部改变文化时,有没有办法可以触发这一点?
我想指出 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 绑定即可反映数字格式改变。