MAUI中实现CollectionView内Entry自动跳转至下一个输入框的方法
实现CollectionView中Entry输入后自动跳转焦点的方案
问题分析
原代码存在两处关键问题:
Name="{Binding CharIndex}"是错误用法——XAML中x:Name仅支持静态字符串,无法绑定动态值- 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; } }
关键说明
- 优先通过
BindingContext匹配控件与ViewModel,避免依赖控件名称 - 支持两种触发方式:回车触发(
Completed事件)、输入完成自动触发(TextChanged事件) - 递归查找布局容器中的Entry,适配复杂ItemTemplate结构
- 最后一个Entry会自动终止跳转逻辑
内容的提问来源于stack exchange,提问作者Filip Wtterwulghe
相关产品推荐
相关产品推荐

