C#WPF选项卡导航以从ListBox外部控制ListBoxItem内部

时间:2018-02-19 20:35:50

标签: c# wpf tabnavigator

我有一个带有版本文本框,按钮和ListBox扩展和收缩的窗口。每个ListBox项都有多个文本框。我正在尝试找到一种方法,以便从ListBox的{​​{1}}外部导航到TextBox的第一个项目中的第一个ListBox。我可以让它导航到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>

2 个答案:

答案 0 :(得分:0)

只需制作ListBox IsTabStop="False"和LitBoxItemStyle。 我将此setter添加到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>

答案 1 :(得分:0)

所以,这可能不是理想的做法,但它确实有效。首先,我们将绑定标记添加到TextBox

中的DataTemplate
    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",
                });

下一步是在此控件之前的用户控件中添加KeyDown事件。在那种情况下,我们会找到带有该标签的元素,然后使用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);
            }));
        }
    }

正如你所看到的,为了更简单的事情,你需要做很多工作。