c# - Xamarin 表单条目小数分隔符在不同的 CultureInfo 上无法正常工作
问题描述
我在 xaml 中有一个条目:
<Entry Grid.Column="1" Grid.RowSpan="1"
FontAttributes="None" FontSize="Large"
IsPassword="False" Keyboard="Numeric"
HorizontalTextAlignment="Center" VerticalOptions="StartAndExpand"
Text="{Binding MyNumber}"
TextColor="{Binding PropertyTextColor, Converter={StaticResource StringToColorConverter}}"
Completed="Entry_Completed"/>
当我有美国文化信息时,一切正常,但是当文化信息发生变化时,我无法输入逗号或点分隔符进行十进制输入。例如,当我键入 5 并输入 ',' 并键入 5 时,该值将转换为 55。我尝试更改当前线程的区域性信息,但它没有帮助。
private decimal _myNumber;
public decimal MyNumber
{
get
{
return myNumber;
}
set
{
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
if (_myNumber != value)
{
if (IsDivisible)
//_myNumber = Convert.ToDecimal(Math.Round(value, 2).ToString(), new CultureInfo("pl-PL"));
_ = decimal.TryParse(value.ToString(), NumberStyles.Any, new CultureInfo("pl-PL"), out _count);
else
_ = decimal.TryParse(value.ToString(), NumberStyles.Any, new CultureInfo("pl-PL"), out _count);
// _myNumber = Convert.ToDecimal(Math.Round(value, 0).ToString(), new CultureInfo("pl-PL"));
OnPropertyChanged(nameof(Count));
}
}
}
有没有办法解决这个问题?因为据我了解,此问题与三星配置或设置有关,并且在 Xamarin 中是一个很常见的问题。
解决方案
在我的情况下,我最终需要强制将点作为每种文化的小数分隔符。为了打印点,我还需要为条目创建一个自定义渲染器,以便重新设置 InputTypes 标志。
如果这听起来像是您可能想要遵循的方式,请继续阅读。
下面是一个示例最少的应用程序,用于演示如何在 Android 中为 Xamarin.Forms 强制和使用点作为小数分隔符
强制点作为小数分隔符
首先我们要告诉 App,无论使用什么文化,点都必须作为小数分隔符:
public App()
{
CultureInfo customCulture = (CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
customCulture.NumberFormat.NumberDecimalSeparator = ".";
System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;
InitializeComponent();
MainPage = new MainPage();
}
重新设置输入类型
在 Xamarin.Forms 共享项目上创建一个 CustomEntry:
using Xamarin.Forms;
namespace EntryDecimal
{
public class MyCustomEntry : Entry
{
}
}
然后在 Android 上添加自定义渲染器。为此,只需向 Android 项目添加一个名为 AndroidCustomEntryRenderer.cs 的新类,其内容如下:
using System.ComponentModel;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Text.Method;
using Android.Content;
using EntryDecimal.Droid;
using EntryDecimal;
[assembly: ExportRenderer(typeof(MyCustomEntry), typeof(AndroidCustomEntryRenderer))]
namespace EntryDecimal.Droid
{
public class AndroidCustomEntryRenderer : EntryRenderer
{
private MyCustomEntry element;
private EditText native;
public AndroidCustomEntryRenderer(Context context) : base(context)
{ }
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
//Java.Text.DecimalFormatSymbols.Instance.DecimalSeparator = '.';
element = (MyCustomEntry)Element ?? null;
native = Control as EditText;
UpdateKeyboard();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Control == null) return;
else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
UpdateKeyboard();
}
private void UpdateKeyboard()
{
//Implementation of the numeric keyboard (we simply add the NumberFlagSigned)
native = Control as EditText;
var defaultNumericKeyboard = Android.Text.InputTypes.ClassNumber | Android.Text.InputTypes.NumberFlagDecimal;
var correnctNumericKeyboard = Android.Text.InputTypes.ClassNumber | Android.Text.InputTypes.NumberFlagSigned | Android.Text.InputTypes.NumberFlagDecimal;
if (native.InputType == defaultNumericKeyboard)
{
native.InputType =
Android.Text.InputTypes.ClassNumber |
Android.Text.InputTypes.NumberFlagSigned |
Android.Text.InputTypes.NumberFlagDecimal;
native.KeyListener = DigitsKeyListener.GetInstance(string.Format("7890.-"));
}
else if (native.InputType == correnctNumericKeyboard)
{
// Even though in the next line the InputType is set to the same it is already set, this seems to
// fix the problem with the decimal separator: Namely, a local other than english is set, the point
// does not have any effect in the numeric keyboard. Re-setting the InputType seems to fix this.
native.InputType =
Android.Text.InputTypes.ClassNumber |
Android.Text.InputTypes.NumberFlagSigned |
Android.Text.InputTypes.NumberFlagDecimal;
}
}
}
}
最后消费这个:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:EntryDecimal"
x:Class="EntryDecimal.MainPage">
<StackLayout>
<local:MyCustomEntry x:Name="MyEntry" Keyboard="Numeric"
WidthRequest="150"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Completed="MyCustomEntry_Completed"/>
</StackLayout>
</ContentPage>
这个最小的空白应用程序在我这边工作正常,接受点作为任何文化的小数分隔符(例如 de [german],其中小数分隔符是“,”)。
希望这有效!
推荐阅读
- android - 在android中从一个活动显示数据到另一个活动
- javascript - 使用解析的 json 作为 javascript 对象时出现“未定义”参数错误
- html - 在 HTML 输入标记中显示 .p7m 文件的接受属性的正确值是多少?
- jenkins - 詹金斯缺少构建
- python - 分配的变量少于函数返回的变量
- r - R Lmer 输出 - 具有多个级别的因子的单个模型汇总输出
- asp.net-mvc - 如何在导航栏中使用 ContentResult 返回(部分视图)
- excel - 由于大范围的行,文件没有响应?
- python - Python中的标签分割
- regex - 验证巴基斯坦手机号码的正确正则表达式是什么?