Подтвердить что ты не робот

Вкладка между элементами списка WPF

У меня есть список, в котором каждый элемент представлен с помощью текстового поля. Дело в том, что я хочу иметь возможность вставлять вкладку между всеми элементами в списке, прежде чем переходить к следующему элементу в окне xaml.

Текущее (и нормальное поведение WPF) заключается в том, что когда я вставляю в список, первый элемент подсвечивается, если я снова нажимаю, то фокус перемещается в текстовое поле внутри этого элемента. Если я снова закрою, фокус перемещается к следующему элементу в окне (без прохождения каких-либо других элементов в ListBox).

Поведение, которое я хочу, следующее: Когда я вставляю в список, первое текстовое поле автоматически получает фокус (без выделения всего элемента) *. Если я снова наберу, то следующее текстовое поле в списке будет сосредоточено. Когда я вставляю последнее текстовое поле в списке, затем фокус переходит к следующему элементу управления.

* Я уже как это делаю, я просто размещаю его здесь, чтобы объяснить весь процесс.

Я искал решение, и я не смог что-то найти.

4b9b3361

Ответ 1

Это можно сделать в xaml, установив следующие два свойства.

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

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

Для полного объяснения см. Запись в блоге Derek Wilson.

Ответ 2

ИЗМЕНИТЬ

После комментария, чтобы быть конкретным:

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 гарантирует, что обработчик обработан только нажатием на вкладку, а поведение по умолчанию не будет активировано.