C#WPF TAB导航到ListBox外部的ListBoxItem内部的控制



我有一个带有版本文本框,按钮和ListBox的窗口,该窗口扩展和合同。每个ListBox项目都有多个文本框。我正在尝试找到一种方法,以从ListBox的外部导航到ListBox的第一个项目中的第一个TextBox。我可以让它导航到ListBox本身,如果我击中向下箭头键,它将选择第一个项目,但这很笨拙。我需要它直接从ListBox外的某些东西到ListBox中的某些东西。

以下是我用于ListBox的XAML。

                    <ListBox x:Name="add_users_listbox" Margin="2,116,-8,0" BorderThickness="0" Height="322" Padding="0,0,0,0"
                             HorizontalContentAlignment="Center" VerticalContentAlignment="Top" 
                             HorizontalAlignment="Center" VerticalAlignment="Top"
                             SelectionMode="Single"
                             IsTabStop="True"
                             TabIndex="1004"
                             Background="{x:Null}" BorderBrush="{x:Null}"
                             ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                             ScrollViewer.CanContentScroll="False"
                             ItemsSource="{Binding Add_User_Binding}"
                             SelectedIndex="{Binding Add_User_Selected_Index, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
                        <ListBox.Resources>
                            <Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource ScrollBar_Rounded}"/>
                            <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource CustomListBoxItemStyle}"/>
                            <Style TargetType="{x:Type ListBox}" >
                                <Setter Property="KeyboardNavigation.TabNavigation" Value="Continue" />
                            </Style>
                        </ListBox.Resources>
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Grid Height="60" Background="Transparent"
                                      HorizontalAlignment="Center" VerticalAlignment="Top">
                                    <TextBox Height="26" Width="102" Padding="0,-1,0,1" Margin="2,2,0,0"
                                                 HorizontalAlignment="Left" VerticalAlignment="Top" HorizontalContentAlignment="Left" VerticalContentAlignment="Center"
                                                 FontFamily="Segoe UI" FontSize="16" FontWeight="Bold"
                                                 TextWrapping="NoWrap" IsReadOnlyCaretVisible="True" UndoLimit="10" AllowDrop="False" MaxLines="1"
                                                 TabIndex="{Binding First_TabIndex}"
                                                 MaxLength="20"
                                                 TextChanged="first_last_textbox_TextChanged"
                                                 PreviewTextInput="first_last_textbox_PreviewTextInput"
                                                 Text="{Binding First_Textbox, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, ValidatesOnDataErrors=True}">
                                    </TextBox>
                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

也只需使您的列表框IsTabStop="False"和litboxItemstyle即可。我将此设置器添加到ListBoxItemstyle:<Setter Property="IsTabStop" Value="False"/>

  <ListBox x:Name="add_users_listbox" Grid.Row="1"  BorderThickness="0" Height="322" Padding="0,0,0,0"
                         HorizontalContentAlignment="Center" VerticalContentAlignment="Top" 
                         HorizontalAlignment="Center" VerticalAlignment="Top"
                         SelectionMode="Single"
                         IsTabStop="False"
                         TabIndex="1004"
                         Background="{x:Null}" BorderBrush="{x:Null}"
                         ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                         ScrollViewer.CanContentScroll="False"
                         ItemsSource="{Binding Add_User_Binding}"
                         SelectedIndex="{Binding Add_User_Selected_Index, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
        <ListBox.Resources>
            <Style TargetType="{x:Type ScrollBar} BasedOn="{StaticResource ScrollBar_Rounded}" "/> 
            <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource CustomListBoxItemStyle}">                     
                <Setter Property="IsTabStop" Value="False"/>
            </Style>
            <Style TargetType="{x:Type ListBox}" >
                <Setter Property="KeyboardNavigation.TabNavigation" Value="Continue" />
            </Style>
        </ListBox.Resources>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Height="60" Background="Transparent"
                                  HorizontalAlignment="Center" VerticalAlignment="Top">
                    <TextBox Height="26" Width="102" Padding="0,-1,0,1" Margin="2,2,0,0"
                                             HorizontalAlignment="Left" VerticalAlignment="Top" HorizontalContentAlignment="Left" VerticalContentAlignment="Center"
                                             FontFamily="Segoe UI" FontSize="16" FontWeight="Bold"
                                             TextWrapping="NoWrap" IsReadOnlyCaretVisible="True" UndoLimit="10" AllowDrop="False" MaxLines="1"                                                  
                                             MaxLength="20"
                                             TextChanged="first_last_textbox_TextChanged"
                                             PreviewTextInput="first_last_textbox_PreviewTextInput"
                                             Text="{Binding First_Textbox, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}">
                    </TextBox>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

因此,这可能不是这样做的理想方式,但它起作用。首先,我们在DataTemplate中的TextBox添加了一个绑定标签

    ItemsSource="{Binding ListBox_Item_Collection}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBox Text="{Binding First_Textbox, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
                         Tag="{Binding Index}">
                </TextBox>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>

为简单起见,我将该标签绑定到ItemSource集合中的相应索引。

                int index = Add_User_Binding.Count;
                ListBox_Item_Collection.Add(new SomeDataType()
                {
                    Index = index,
                    The_Textbox = "Stuff in TextBox",
                });

下一步是在此之前的用户控件中添加键盘事件。在这种情况下,我们将找到带有该标签的元素,然后使用Dispatcher将其聚焦。

    private void Preview_TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Tab)
        {
            string tag = "0";
            IEnumerable<TextBox> elements = FindVisualChildren<TextBox>(this).Where(x => x.Tag != null && x.Tag.ToString() == tag);
            foreach (TextBox element in elements)
            {
                FocusElement(element);
            }
        }
    }
    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }
                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    }
    private void FocusElement(IInputElement element)
    {
        if (element != null)
        {
            Dispatcher.BeginInvoke
            (System.Windows.Threading.DispatcherPriority.ContextIdle,
            new Action(delegate ()
            {
                Keyboard.Focus(element);
            }));
        }
    }

您可以看到,很多工作应该更简单。

最新更新