Вкладка между элементами списка WPF - PullRequest
24 голосов
/ 14 июля 2009

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

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

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

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

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

Ответы [ 2 ]

67 голосов
/ 13 августа 2010

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

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

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

Полное объяснение см. Блог Дерека Уилсона .

0 голосов
/ 14 июля 2009

EDIT

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...