Я пытаюсь получить эквивалент WinForms ListView с его свойством View, установленным на View.List. Визуально все работает нормально. Имена файлов в моем Listbox идут сверху вниз, а затем переносятся в новый столбец.
Вот базовый XAML, с которым я работаю:
<ListBox Name = "thelist"
IsSynchronizedWithCurrentItem = "True"
ItemsSource = "{Binding}"
ScrollViewer.VerticalScrollBarVisibility = "Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost = "True"
Orientation = "Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Однако навигация по клавишам со стрелками по умолчанию не переносится. Если выбран последний элемент в столбце, нажатие стрелки вниз не приводит к переходу к первому элементу следующего столбца.
Я пробовал обрабатывать событие KeyDown следующим образом:
private void thelist_KeyDown( object sender, KeyEventArgs e ) {
if ( object.ReferenceEquals( sender, thelist ) ) {
if ( e.Key == Key.Down ) {
e.Handled = true;
thelist.Items.MoveCurrentToNext();
}
if ( e.Key == Key.Up ) {
e.Handled = true;
thelist.Items.MoveCurrentToPrevious();
}
}
}
Это приводит к желаемому мной поведению от последнего в столбце до первого в следующем столбце, но также вызывает странность в обработке стрелок влево и вправо. Каждый раз, когда выполняется перенос от одного столбца к следующему / предыдущему с помощью стрелок вверх / вниз, однократное последующее использование клавиши со стрелкой влево или вправо перемещает выделение влево или вправо от элемента, который был выбран непосредственно перед выполнением переноса.
Предположим, что список заполнен строками от «0001» до «0100», по 10 строк в столбце. Если я использую клавишу со стрелкой вниз для перехода от «0010» к «0011», затем нажимаю клавишу со стрелкой вправо, выбор перемещается на «0020», справа от «0010». Если выбрано «0011» и я использую клавишу со стрелкой вверх, чтобы переместить выделение на «0010», то нажатие клавиш со стрелкой вправо перемещает выделение на «0021» (справа от «0011», а нажатие левой клавиша со стрелкой перемещает выделение на «0001».
Приветствуется любая помощь в достижении желаемого макета с переносом столбцов и навигации с помощью клавиш со стрелками.
(Изменения перенесены в мой собственный ответ, поскольку технически это ответ.)





Оказывается, когда он завершается моей обработкой события KeyDown, выбор изменяется на правильный элемент, но основное внимание уделяется старому элементу.
Вот обновленный обработчик событий KeyDown. Из-за привязки коллекция Items возвращает мои фактические элементы, а не ListBoxItem, поэтому мне нужно сделать вызов ближе к концу, чтобы получить фактический ListBoxItem, который мне нужно вызвать Focus(). Переход от последнего элемента к первому и наоборот может быть достигнут путем замены вызовов MoveCurrentToLast() и MoveCurrentToFirst().
private void thelist_KeyDown( object sender, KeyEventArgs e ) {
if ( object.ReferenceEquals( sender, thelist ) ) {
if ( thelist.Items.Count > 0 ) {
switch ( e.Key ) {
case Key.Down:
if ( !thelist.Items.MoveCurrentToNext() ) {
thelist.Items.MoveCurrentToLast();
}
break;
case Key.Up:
if ( !thelist.Items.MoveCurrentToPrevious() ) {
thelist.Items.MoveCurrentToFirst();
}
break;
default:
return;
}
e.Handled = true;
ListBoxItem lbi = (ListBoxItem) thelist.ItemContainerGenerator.ContainerFromItem( thelist.SelectedItem );
lbi.Focus();
}
}
}
Вы должны иметь возможность сделать это без прослушивателя событий, используя KeyboardNavigation.DirectionalNavigation, например
<ListBox Name = "thelist"
IsSynchronizedWithCurrentItem = "True"
ItemsSource = "{Binding}"
ScrollViewer.VerticalScrollBarVisibility = "Disabled"
KeyboardNavigation.DirectionalNavigation = "Cycle">
Отлично, это мне очень помогло. ;)