列表元素之间的选项卡 WPF

问题描述 投票:0回答:3

我有一个列表框,其中每个项目都使用文本框表示。问题是我希望能够在移动到 xaml 窗口中的下一个元素之前在列表框中的所有项目之间进行切换。

当前(和正常的 WPF 行为)是,当我按 Tab 键进入列表框时,第一个元素会突出显示,如果我再次按 Tab 键,则焦点将移至该项目内的文本框中。如果我再次按 Tab 键,焦点将移动到窗口中的下一个元素(而不经过列表框中的任何其他项目)。

我想要的行为如下:当我点击列表框时,第一个文本框自动获得焦点(不突出显示整个项目)*。如果我再次按 Tab 键,则列表框中的下一个文本框将获得焦点。当我点击列表框中的最后一个文本框时,焦点将移动到下一个控件。

*我已经知道如何做到这一点,我只是将其发布在这里以解释完整的过程。

我一直在寻找解决方案,但一直找不到任何东西。

wpf xaml
3个回答
75
投票

这可以在 xaml 中通过设置以下两个属性来完成。

    <Style TargetType="ListBox" >
        <Setter Property="KeyboardNavigation.TabNavigation" Value="Continue" />
    </Style>

    <Style TargetType="ListBoxItem">
        <Setter Property="IsTabStop" Value="False" />
    </Style>

有关完整说明,请参阅 Derek Wilson 的博客文章


0
投票

编辑

评论后,具体来说:

private void ListBox_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Tab)
    {
        ListBox lb = sender as ListBox;

        if(lb == null) return;

        if(lb.SelectedIndex < lb.Items.Count - 1)
        {
            GiveItemFocus(lb, lb.SelectedIndex + 1, typeof(TextBox));
            e.Handled = true;
        }
    }
}

private void GiveItemFocus(ListBox lb, int index, Type descentdantType)
{
    if(lb.Items.Count >= index || index < 0)
    {
        throw new ArgumentException();
    }

    ListBoxItem lbi = (ListBoxItem) lb.ItemContainerGenerator.ContainerFromIndex(index);

    lb.UnselectAll();

    lbi.IsSelected = true;

    UIElement descendant = (UIElement) FindVisualDescendant(lbi, o => o.GetType() == descentdantType);

    descendant.Focus();
}

private static DependencyObject FindVisualDescendant(DependencyObject dependencyObject, Predicate<bool> condition)
{
    //implementation not provided, commonly used utility
}

e.Handled
设置为 true 将确保仅在按 Tab 键时处理您的处理程序,并且不会激活默认行为。


0
投票
Here is the complete implementation

  <ListBox
  Margin="15"
  HorizontalContentAlignment="Stretch"
  Background="Transparent"
  BorderBrush="Transparent"
  IsTabStop="False"
  ItemsSource="{Binding SelectedTemplate.TemplateFields}"
  KeyboardNavigation.TabNavigation="Continue"
  ScrollViewer.HorizontalScrollBarVisibility="Disabled">

  <ListBox.ItemTemplate>
      <DataTemplate>
          <TextBox />
      </DataTemplate>
  </ListBox.ItemTemplate>
  <ListBox.ItemContainerStyle>
      <Style TargetType="{x:Type ListBoxItem}">
          <Setter Property="IsTabStop" Value="False" /> 
      </Style>
  </ListBox.ItemContainerStyle>
© www.soinside.com 2019 - 2024. All rights reserved.