wpf ListBox中所有文本框回车跳到下个文本框.

我用的Mvvm框架.

我的ListBox有十行三列的文本框,回车会跳到下一个,一列到底回车跳到下一列,到最后一个又会跳到第一个.并且跳到文本框文本框中的文字会被全部选中.代码如下.

xmal

<ListBox ItemsSource="{Binding XXX}" x:Name="lb" SelectionMode="Single" Grid.Row="1" BorderThickness="0">
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border BorderThickness="1,0,1,1" BorderBrush="#999999" HorizontalAlignment="Stretch" Margin="0" Padding="0">
                            <Grid HorizontalAlignment="Stretch" Height="54">
                                <Grid.Resources>
                                    <Style TargetType="TextBlock" BasedOn="{StaticResource tbx}">
                                        <Setter Property="VerticalAlignment" Value="Center" />
                                        <Setter Property="HorizontalAlignment" Value="Center" />
                                        <Setter Property="FontSize" Value="28" />
                                        <Setter Property="Width" Value="Auto" />
                                    </Style>
                                </Grid.Resources>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="79" />
                                    <ColumnDefinition />
                                    <ColumnDefinition Width="79" />
                                    <ColumnDefinition />
                                    <ColumnDefinition Width="79" />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <TextBlock Text="{Binding No1}" />
                                <TextBox Text="{Binding t1}" Grid.Column="1" Width="282" Height="53" BorderThickness="0" >
                                    <TextBox.InputBindings>
                                        <KeyBinding Key="Enter" Command="{Binding DataContext.MoveFocusCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                                             CommandParameter="{Binding RelativeSource={RelativeSource  AncestorType=TextBox}}"/>
                                        <TextBox.InputBindings>
                                            <i:Interaction.Triggers>
                                                <i:EventTrigger EventName="TextChanged">
                                                    <i:InvokeCommandAction Command="{Binding DataContext.TextChangedCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
    CommandParameter="{Binding RelativeSource={RelativeSource  AncestorType=TextBox}}"/>
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                    </TextBox>

                                                    <TextBlock Text="{Binding No2}" Grid.Column="2" />
                                                    <TextBox Text="{Binding t2}" Grid.Column="3" Width="282" Height="53" BorderThickness="0" >
                                                        <TextBox.InputBindings>
                                                            <KeyBinding Key="Enter" Command="{Binding DataContext.MoveFocusCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                                                                        CommandParameter="{Binding RelativeSource={RelativeSource  AncestorType=TextBox}}"/>
                                                        </TextBox.InputBindings>
                                                        <i:Interaction.Triggers>
                                                            <i:EventTrigger EventName="TextChanged">
                                                                <i:InvokeCommandAction Command="{Binding DataContext.TextChangedCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                                                                                       CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=TextBox}}"/>
                                                            </i:EventTrigger>
                                                        </i:Interaction.Triggers>
                                                    </TextBox>

                                                    <TextBlock Text="{Binding No3}" Grid.Column="4" />
                                                    <TextBox Text="{Binding t3}" Grid.Column="5" Width="282" Height="53" BorderThickness="0" >
                                                        <TextBox.InputBindings>
                                                            <KeyBinding Key="Enter" Command="{Binding DataContext.MoveFocusCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                                                                        CommandParameter="{Binding RelativeSource={RelativeSource  AncestorType=TextBox}}"/>
                                                        </TextBox.InputBindings>
                                                        <i:Interaction.Triggers>
                                                            <i:EventTrigger EventName="TextChanged">
                                                                <i:InvokeCommandAction Command="{Binding DataContext.TextChangedCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                                                                                           CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=TextBox}}"/>
                                                            </i:EventTrigger>
                                                        </i:Interaction.Triggers>
                                                    </TextBox>

                                                    <Border BorderThickness="1" BorderBrush="#999999" Grid.Column="1" HorizontalAlignment="Left" Width="1" />
                                                    <Border BorderThickness="1" BorderBrush="#999999" Grid.Column="2" HorizontalAlignment="Left" Width="1" />
                                                    <Border BorderThickness="1" BorderBrush="#999999" Grid.Column="3" HorizontalAlignment="Left" Width="1" />
                                                    <Border BorderThickness="1" BorderBrush="#999999" Grid.Column="4" HorizontalAlignment="Left" Width="1" />
                                                    <Border BorderThickness="1" BorderBrush="#999999" Grid.Column="5" HorizontalAlignment="Left" Width="1" />
                                                </Grid>
                                            </Border>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </ListBox.Resources>
                    </ListBox>

xmal.cs  这里也可以ListBox的Loaded事件,就不用给ListBox取名字了.暂时还不知这两种有什么区别,哪种更好一点.

 Loaded += (s, e) => { Vm.Load(lb); };

ViewModel.cs

System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<TextBox>> boxlist { get; set; } = new System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<TextBox>>();
        public void Load(ListBox lb)
        {
            boxlist = Util.FindTextBoxesInListBox(lb);
        }

  /// <summary>
        /// 文本框回车向下
        /// </summary>
        public ICommand MoveFocusCommand => new RelayCommand<TextBox>(textBox =>
        {
            if (textBox == null) return;
            // 获取当前ListBox
            var listBox = FindVisualParent<ListBox>(textBox);
            if (listBox == null) return;

            // 获取当前行和列
            var currentItem = textBox.DataContext;
            var currentColumn = Grid.GetColumn(textBox);

            // 获取所有行
            var items = listBox.Items.Cast<object>().ToList();
            // 查找当前行索引
            var currentIndex = items.IndexOf(currentItem);
            // 计算下一行索引
            var nextIndex = currentIndex + 1;
            if (nextIndex >= 10)
            {
                // 如果已经是最后一行,跳转到下一列的第一行
                nextIndex = 0;
                currentColumn += 2; // 列间隔为2(因为列定义是交替的)
            }

            // 如果列超出范围,回到第一列
            if (currentColumn > 5)
            {
                currentColumn = 1;
            }

            // 获取下一行的文本框
            var nextTextBox = boxlist.FirstOrDefault(x => x.Key == currentColumn).Value[nextIndex];
            if (nextTextBox != null)
            {
                nextTextBox.Focus();
                nextTextBox.SelectAll();
            }
            else
            {
                // 如果找不到对应列的文本框,继续查找
                MoveFocusCommand.Execute(nextTextBox);
            }
        });
// Helper methods
        private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
        {
            var parentObject = VisualTreeHelper.GetParent(child);
            if (parentObject == null) return null;
            return parentObject is T parent ? parent : FindVisualParent<T>(parentObject);
        }

        private static T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
        {
            try
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    if (child is T result) { return result; }
                    var childResult = FindVisualChild<T>(child);
                    if (childResult != null) { return childResult; }
                }
            }
            catch (Exception)
            {
               throw;
            }

            return null;
        }

   

Util.cs

public static Dictionary<int, List<TextBox>> FindTextBoxesInListBox(ListBox listBox)
        {
            // 创建一个字典,用于存储按列索引分组的 TextBox
            var doubleTextBoxColumns = new Dictionary<int, List<TextBox>>();

            // 遍历 ListBox 中的每一项
            for (int i = 0; i < listBox.Items.Count; i++)
            {
                // 获取 ListBoxItem
                var listBoxItem = listBox.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;

                if (listBoxItem != null)
                {
                    // 查找 Grid
                    var grid = FindVisualChilds<Grid>(listBoxItem);
                    if (grid != null)
                    {
                        // 获取每个 TextBox
                        FindDoubleTextBoxesInGrid(grid, doubleTextBoxColumns);
                    }
                }
            }
            return doubleTextBoxColumns;
        }

        // 查找 Grid 中的所有 TextBox,并按列索引分组
        private static void FindTextBoxesInGrid(Grid grid, Dictionary<int, List<TextBox>> doubleTextBoxColumns)
        {
            // 遍历 Grid 的所有子元素
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++)
            {
                var child = VisualTreeHelper.GetChild(grid, i);

                // 检查是否为 TextBox
                if (child is TextBox doubleTextBox)
                {
                    // 获取该 TextBox 所在的列索引
                    int column = Grid.GetColumn(doubleTextBox);
                    // 确保字典中有该列
                    if (!doubleTextBoxColumns.ContainsKey(column))
                    {
                        doubleTextBoxColumns[column] = new List<TextBox>();
                    }

                    // 将 TextBox 添加到对应的列列表中
                    doubleTextBoxColumns[column].Add(doubleTextBox);
                }

                // 如果子元素是 Grid,递归查找
                if (child is Panel panel)
                {
                    FindDoubleTextBoxesInGrid(panel as Grid, doubleTextBoxColumns);
                }
            }
        }

        // 通用查找视觉子元素的方法
        private static T FindVisualChilds<T>(DependencyObject parent) where T : DependencyObject
        {
            int count = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                if (child is T typedChild)
                {
                    return typedChild;
                }

                var childOfChild = FindVisualChilds<T>(child);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
            return null;
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值