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

.NET MAUI升级到9.0后货币输入控件报end should be < than charSequence length错误

.NET MAUI 9.0自定义货币Entry控件报错:Java.Lang.IllegalArgumentException: 'end should be < than charSequence length'

我在.NET MAUI应用中实现了一个响应式货币输入Entry控件,初始显示R$ 0,00:输入5后变为R$ 0,05,输入3后变为R$ 0,53,功能原本完全正常。但将.NET版本升级到9.0后,当输入到R$ 159,00再按0时,触发如下错误:

Java.Lang.IllegalArgumentException: 'end should be < than charSequence length'

怀疑是格式化后金额中的千分位“.”导致了该问题,相关代码如下:

using System.Globalization;

namespace Mobile;
public class EntryValores : Entry
{
    private bool executingTextChanged = false;

    public EntryValores()
    {
       // HorizontalTextAlignment = TextAlignment.End;
        TextChanged += EntryValores_OnTextChanged;
    }

    protected void EntryValores_OnTextChanged(object sender, TextChangedEventArgs e)
    {
        if (executingTextChanged) return;
        executingTextChanged = true;

        // Formatar valores
        decimal valor;
        string valorTexto = "0";

        // Retornar apenas os dígitos
        foreach (char c in Text)
        {
            if (char.IsDigit(c))
            {
                valorTexto += c;
            }
        }

        // Se for Nulo, então colocar 0
        if (string.IsNullOrEmpty(valorTexto))
        {
            valorTexto = "0";
        }

        valor = decimal.Parse(valorTexto) / 100;

        // Verificar limites
        if (valor > 999999999999m || valor < -999999999999m)
        {
            // Se o valor for maior que 100 trilhões ou menor que -100 trilhões, cancelar a entrada
            Text = e.OldTextValue;
        }
        else
        {
            // Colocar o valor formatado
            Text = valor.ToString("C", CultureInfo.CurrentCulture);
        }

        executingTextChanged = false;
    }
}

问题原因

这个错误本质是Android端Entry控件的光标位置计算异常。.NET MAUI 9.0对Android平台的文本输入控件逻辑做了调整:当你在TextChanged事件中直接替换文本时,若格式化后的文本因千分位插入了额外字符(比如输入0后R$ 159,00变为R$ 1.590,00,多了一个.),控件内部的光标位置没有同步更新,导致尝试访问超出字符长度的索引,触发参数错误。

修复方案

方案1:手动同步光标位置(快速修复)

在更新Text后,强制将光标移到文本末尾,避免控件内部光标位置错乱:

else
{
    // Colocar o valor formatado
    Text = valor.ToString("C", CultureInfo.CurrentCulture);
    // 新增:将光标定位到文本末尾
    Dispatcher.Dispatch(() =>
    {
        if (!string.IsNullOrEmpty(Text))
        {
            CursorPosition = Text.Length;
            SelectionLength = 0;
        }
    });
}

使用Dispatcher.Dispatch是为了确保光标操作在UI线程执行,避免跨线程异常。

方案2:通过绑定属性处理(更稳妥)

改用绑定属性+转换器的方式处理格式化,避开直接修改Text带来的光标同步问题:

  1. 新增绑定属性:
public static readonly BindableProperty ValueProperty =
    BindableProperty.Create(nameof(Value), typeof(decimal), typeof(EntryValores), 0m,
        propertyChanged: (bindable, oldValue, newValue) =>
        {
            var entry = (EntryValores)bindable;
            if (!entry.executingTextChanged)
            {
                entry.executingTextChanged = true;
                entry.Text = ((decimal)newValue).ToString("C", CultureInfo.CurrentCulture);
                entry.executingTextChanged = false;
            }
        });

public decimal Value
{
    get => (decimal)GetValue(ValueProperty);
    set => SetValue(ValueProperty, value);
}
  1. 修改TextChanged逻辑,更新绑定属性而非直接修改Text:
protected void EntryValores_OnTextChanged(object sender, TextChangedEventArgs e)
{
    if (executingTextChanged) return;
    executingTextChanged = true;

    // 简化数字提取逻辑
    string valorTexto = string.Concat(Text.Where(char.IsDigit));
    valorTexto = string.IsNullOrEmpty(valorTexto) ? "0" : valorTexto;

    if (decimal.TryParse(valorTexto, out decimal rawValue))
    {
        decimal valor = rawValue / 100;
        if (valor > 999999999999m || valor < -999999999999m)
        {
            // 超出范围则保持原值
            Value = (decimal)GetValue(ValueProperty);
        }
        else
        {
            Value = valor;
        }
    }
    else
    {
        Value = 0m;
    }

    executingTextChanged = false;
}

额外优化

  • 用string.Concat(Text.Where(char.IsDigit))替代遍历字符的逻辑,更简洁高效。
  • 替换decimal.Parse为decimal.TryParse,避免非法输入导致的解析异常。

内容的提问来源于stack exchange,提问作者Heitor Badotti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:15:03