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

.NET 9 MAUI Entry控件动态格式化印度数字时光标位置异常求助

解决MAUI .NET9中数字格式化后光标位置异常问题

问题根源

升级到.NET9后,动态格式化数字时,双向绑定触发的TextChanged事件会覆盖光标位置设置,且未考虑印度格式(hi-IN)中分隔符对光标位置的影响,导致光标跳至错误位置。

解决方案步骤

  1. 区分用户输入与绑定更新:添加标志位避免循环触发TextChanged事件;
  2. 精准计算光标位置:遍历格式化后的文本,定位到用户最后输入数字的后方;
  3. 优化ViewModel格式化逻辑:同步处理数字格式化,避免异步引发的时序问题。

修改后的代码

后台代码(Page.xaml.cs)

private bool _isUpdatingFromViewModel;

private void OnTextChanged(object sender, TextChangedEventArgs e) 
{
    if (_isUpdatingFromViewModel || string.IsNullOrEmpty(e.NewTextValue))
        return;

    // 仅处理用户输入的纯数字(Numeric键盘输入无逗号)
    if (e.NewTextValue.Any(c => !char.IsDigit(c)))
        return;

    string rawDigits = e.NewTextValue;
    int newDigitCount = rawDigits.Length;

    _isUpdatingFromViewModel = true;
    try
    {
        updateCounterPageViewModel.CounterChanged(rawDigits);
        
        // 延迟到UI线程绑定更新完成后设置光标
        CurrentCounterEntry.Dispatcher.Dispatch(() => 
        {
            string formattedText = CurrentCounterEntry.Text;
            int cursorPos = 0;
            int digitCount = 0;

            foreach (char c in formattedText)
            {
                if (char.IsDigit(c))
                {
                    digitCount++;
                    if (digitCount == newDigitCount)
                    {
                        cursorPos++;
                        break;
                    }
                }
                cursorPos++;
            }

            // 若已遍历完所有数字,光标移至末尾
            if (digitCount == newDigitCount)
            {
                cursorPos = formattedText.Length;
            }

            CurrentCounterEntry.CursorPosition = cursorPos;
        });
    }
    finally
    {
        _isUpdatingFromViewModel = false;
    }
}

ViewModel代码

public void CounterChanged(string addedCounter)
{
    try
    {
        if (int.TryParse(addedCounter, out int counterInt))
        {
            CurrentCounter = counterInt.ToString("N0", new CultureInfo("hi-IN"));
        }
        else
        {
            CurrentCounter = addedCounter;
        }
    }
    catch (Exception ex)
    {
        // 可添加日志记录逻辑
    }
}

XAML调整(可选,显式声明绑定模式)

<customcontrols:BorderlessEntry
    x:Name="CurrentCounterEntry"
    Placeholder="Enter counter"
    Keyboard="Numeric"
    Text="{Binding CurrentCounter, Mode=TwoWay}"
    TextChanged="OnTextChanged"
    Margin="15,3"
    MaxLength="12"/>

关键说明

  • _isUpdatingFromViewModel标志位:防止ViewModel更新文本时重复触发格式化逻辑,避免循环;
  • 光标位置计算:通过遍历格式化后的文本,精准定位到用户最后输入数字的后方,适配印度格式的分隔符规则;
  • Dispatcher.Dispatch:确保在UI线程上执行光标位置设置,等待绑定更新完成后再操作,避免时序问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:00:15