Вкладка между элементами списка WPF
У меня есть список, в котором каждый элемент представлен с помощью текстового поля. Дело в том, что я хочу иметь возможность вставлять вкладку между всеми элементами в списке, прежде чем переходить к следующему элементу в окне xaml.
Текущее (и нормальное поведение WPF) заключается в том, что когда я вставляю в список, первый элемент подсвечивается, если я снова нажимаю, то фокус перемещается в текстовое поле внутри этого элемента. Если я снова закрою, фокус перемещается к следующему элементу в окне (без прохождения каких-либо других элементов в ListBox).
Поведение, которое я хочу, следующее: Когда я вставляю в список, первое текстовое поле автоматически получает фокус (без выделения всего элемента) *. Если я снова наберу, то следующее текстовое поле в списке будет сосредоточено. Когда я вставляю последнее текстовое поле в списке, затем фокус переходит к следующему элементу управления.
* Я уже как это делаю, я просто размещаю его здесь, чтобы объяснить весь процесс.
Я искал решение, и я не смог что-то найти.
Ответы
Ответ 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 гарантирует, что обработчик обработан только нажатием на вкладку, а поведение по умолчанию не будет активировано.