ListBox+WrapPanel の矢印キーによるナビゲーション
質問
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();
}
}
}
これにより、私が望んでいた列の最後から次の列の最初への動作が生成されますが、左右の矢印の処理に奇妙な動作も生成されます。上/下矢印を使用してある列から次/前の列に折り返すたびに、続けて左または右矢印キーを 1 回使用すると、選択範囲が折り返される直前に選択されていた項目の左または右に移動します。
リストには文字列 "0001" から "0100" が入力されており、各列に 10 個の文字列があるとします。下矢印キーを使用して「0010」から「0011」に移動し、右矢印キーを押すと、選択範囲が「0010」のすぐ右の「0020」に移動します。「0011」が選択されており、上矢印キーを使用して選択範囲を「0010」に移動した場合、右矢印キーを押すと選択範囲が「0021」(「0011」の右側)に移動し、左矢印キーを押すと選択範囲が「0021」に移動します。矢印キーで選択範囲を「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">