You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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模拟器输入,自动变.的问题:
    1. 给Entry设置Keyboard="Numeric",让系统显示对应区域的数字键盘:
      <Entry Keyboard="Numeric" />
      
    2. 输入处理时,先把用户输入的分隔符(.或,)统一转成.再校验,显示时再转回当前区域的分隔符,保证显示和内部处理互不干扰。

二、限制输入格式:允许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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:22:44