.NET MAUI应用处理小数分隔符与多区域设置问题
解决.NET MAUI Entry正Double输入与区域兼容问题
一、让存储/加载不受区域设置干扰
不管当前系统是英语还是德语,存储和读取时统一用**不变文化(InvariantCulture)**处理,彻底避免分隔符差异的问题:
- 存到SQLite时,把double转成带
.的标准字符串:// 示例:把数值转成标准格式存储 double inputValue = 84.2; string storedStr = inputValue.ToString(CultureInfo.InvariantCulture); // 把storedStr写入SQLite即可 - 从SQLite读取时,同样用不变文化解析:
// 示例:从SQLite读出字符串后解析 string storedStr = "84.2"; if (double.TryParse(storedStr, NumberStyles.Float, CultureInfo.InvariantCulture, out double result)) { // 拿到正确的double值result } - 针对Android模拟器输入
,自动变.的问题:- 给Entry设置
Keyboard="Numeric",让系统显示对应区域的数字键盘:<Entry Keyboard="Numeric" /> - 输入处理时,先把用户输入的分隔符(
.或,)统一转成.再校验,显示时再转回当前区域的分隔符,保证显示和内部处理互不干扰。
- 给Entry设置
二、限制输入格式:允许0、0.,禁止.xxx这类无效格式
先修复你现有TextChanged的语法错误+优化校验
原代码有变量声明的语法问题,修正后调整正则逻辑,确保开头不能直接输.:
using System.Globalization; using System.Text.RegularExpressions; private void EntryControl_TextChanged(object sender, TextChangedEventArgs e) { if (sender is not Entry entry) return; string input = entry.Text; string currentSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; // 生成适配当前区域分隔符的正则规则 string regexPattern = $"^(0|0{Regex.Escape(currentSeparator)}[0-9]*|[1-9]+[0-9]*({Regex.Escape(currentSeparator)}[0-9]*)?)$"; var match = Regex.Match(input, regexPattern); if (string.IsNullOrEmpty(input)) { return; } if (!match.Success) { entry.Text = e.OldTextValue; entry.CursorPosition = e.OldTextValue?.Length ?? 0; return; } entry.CursorPosition = e.NewTextValue.Length; }
更省心的复用方案:用Behavior封装校验逻辑
把校验代码做成可复用的Behavior,不用每个Entry都写一遍TextChanged:
public class PositiveDoubleEntryBehavior : Behavior<Entry> { protected override void OnAttachedTo(Entry entry) { entry.TextChanged += OnEntryTextChanged; base.OnAttachedTo(entry); } protected override void OnDetachingFrom(Entry entry) { entry.TextChanged -= OnEntryTextChanged; base.OnDetachingFrom(entry); } private void OnEntryTextChanged(object sender, TextChangedEventArgs e) { if (sender is not Entry entry) return; string input = e.NewTextValue; string currentSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; if (string.IsNullOrEmpty(input)) return; // 直接判断格式合法性 bool isValid = false; // 允许单独的0或0. if (input == "0" || input == $"0{currentSeparator}") { isValid = true; } // 禁止以分隔符开头 else if (input.StartsWith(currentSeparator)) { isValid = false; } // 剩下的情况尝试解析为非负double else { isValid = double.TryParse(input, NumberStyles.Float, CultureInfo.CurrentCulture, out double value) && value >= 0; } if (!isValid) { entry.Text = e.OldTextValue; entry.CursorPosition = e.OldTextValue?.Length ?? 0; } else { entry.CursorPosition = input.Length; } } }
XAML里直接用:
<Entry Keyboard="Numeric"> <Entry.Behaviors> <local:PositiveDoubleEntryBehavior /> </Entry.Behaviors> </Entry>
三、替代正则的简便校验方案
直接用double.TryParse结合当前区域校验,比写正则更直观,还自动适配不同区域的分隔符:
核心逻辑就是每次输入变化时,先排除.xxx这种开头无效的格式,再尝试解析为非负double,合法就保留输入,不合法就回退到上一次的文本。这种方式不用维护复杂的正则表达式,适配性更强。
内容的提问来源于stack exchange,提问作者OXO
相关产品推荐
相关产品推荐

