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

MAUI中实现CollectionView内Entry自动跳转至下一个输入框的方法

实现CollectionView中Entry输入后自动跳转焦点的方案

问题分析

原代码存在两处关键问题:

  1. Name="{Binding CharIndex}" 是错误用法——XAML中x:Name仅支持静态字符串,无法绑定动态值
  2. ViewModel中的ReturnCommand难以直接操作视图控件,不符合MVVM分层原则

以下是直接可行的实现方案:


步骤1:修改XAML布局

给CollectionView命名,绑定Entry的Completed(或TextChanged)事件到页面后台代码,修正绑定逻辑:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp2.RowControlPage"
             xmlns:vm="clr-namespace:MauiApp2.ViewModel"
             Title="RowControlPage">
    <CollectionView x:Name="CharCollectionView">
        <CollectionView.ItemsLayout>
            <LinearItemsLayout Orientation="Horizontal" />
        </CollectionView.ItemsLayout>
        <CollectionView.ItemsSource>
            <x:Array Type="{x:Type vm:CharViewModel}">
                <vm:CharViewModel CharExpected="A" CharTyped="A" CharIndex="1" WordExpected="ABCDEF"/>
                <vm:CharViewModel CharExpected="B" CharTyped="B" CharIndex="2" WordExpected="ABCDEF"/>
                <vm:CharViewModel CharExpected="C" CharTyped="C" CharIndex="3" WordExpected="ABCDEF"/>
                <vm:CharViewModel CharExpected="D" CharTyped="D" CharIndex="4" WordExpected="ABCDEF"/>
                <vm:CharViewModel CharExpected="E" CharTyped="E" CharIndex="5" WordExpected="ABCDEF"/>
                <vm:CharViewModel CharExpected="F" CharTyped="F" CharIndex="6" WordExpected="ABCDEF"/>
            </x:Array>
        </CollectionView.ItemsSource>
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Entry 
                    Text="{Binding CharTyped, Mode=TwoWay}"
                    WidthRequest="70"
                    HeightRequest="70"
                    FontSize="34"
                    Margin="5"
                    Keyboard="Text"
                    HorizontalTextAlignment="Center"
                    VerticalTextAlignment="Center"
                    TextTransform="Uppercase"
                    ReturnType="Next" 
                    MaxLength="1"
                    Completed="OnEntryCompleted"
                    TextChanged="OnEntryTextChanged"/>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

步骤2:实现后台逻辑

在页面代码中处理焦点跳转,通过绑定上下文匹配找到下一个Entry控件:

using Microsoft.Maui.Controls;
using MauiApp2.ViewModel;
using System.Linq;

namespace MauiApp2;

public partial class RowControlPage : ContentPage
{
    public RowControlPage()
    {
        InitializeComponent();
    }

    // 回车触发跳转
    private void OnEntryCompleted(object sender, EventArgs e)
    {
        JumpToNextEntry(sender);
    }

    // 输入单个字符后自动跳转(可选优化)
    private void OnEntryTextChanged(object sender, TextChangedEventArgs e)
    {
        if (sender is Entry currentEntry && currentEntry.Text?.Length == 1)
        {
            JumpToNextEntry(sender);
        }
    }

    private void JumpToNextEntry(object sender)
    {
        if (sender is not Entry currentEntry || currentEntry.BindingContext is not CharViewModel currentVm)
            return;

        var items = CharCollectionView.ItemsSource as IEnumerable<CharViewModel>;
        var nextVm = items?.FirstOrDefault(vm => vm.CharIndex == currentVm.CharIndex + 1);
        if (nextVm == null) return;

        var nextEntry = FindEntryForViewModel(nextVm);
        nextEntry?.Focus();
    }

    // 根据ViewModel查找对应的Entry控件
    private Entry? FindEntryForViewModel(CharViewModel targetVm)
    {
        foreach (var item in CharCollectionView.VisibleItems)
        {
            if (CharCollectionView.TryGetItemView(item, out var itemView))
            {
                if (itemView is Entry entry && entry.BindingContext == targetVm)
                    return entry;
                else if (itemView is Layout layout)
                {
                    var entry = FindEntryInLayout(layout, targetVm);
                    if (entry != null) return entry;
                }
            }
        }
        return null;
    }

    // 递归遍历布局容器查找Entry
    private Entry? FindEntryInLayout(Layout layout, CharViewModel targetVm)
    {
        foreach (var child in layout.Children)
        {
            if (child is Entry entry && entry.BindingContext == targetVm)
                return entry;
            else if (child is Layout childLayout)
            {
                var entry = FindEntryInLayout(childLayout, targetVm);
                if (entry != null) return entry;
            }
        }
        return null;
    }
}

关键说明

  1. 优先通过BindingContext匹配控件与ViewModel,避免依赖控件名称
  2. 支持两种触发方式:回车触发(Completed事件)、输入完成自动触发(TextChanged事件)
  3. 递归查找布局容器中的Entry,适配复杂ItemTemplate结构
  4. 最后一个Entry会自动终止跳转逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 10:45:34