SelectedItem
のListBox
をプログラムで設定し、そのアイテムにフォーカスを持たせて、矢印キーがその選択したアイテムに対して機能するようにします。簡単そうに思えます。
ただし、問題は、ListBox
をプログラムで設定するときにSelectedItem
がすでにキーボードフォーカスを持っている場合、IsSelected
のListBoxItem
プロパティを適切に更新する場合です。 does n'tキーボードフォーカスをそれに設定します。したがって、矢印キーは、リスト内の以前にフォーカスされたアイテムに対して移動します。
キーボードを使用すると、プログラムによる選択が行われる前の位置に戻るため、キーボードを使用すると選択範囲が飛び回るように見えるため、これはユーザーを混乱させます。
注:先ほど言ったように、これは既にキーボードフォーカスを持っているSelectedItem
にListBox
プロパティをプログラムで設定した場合にのみ発生します。キーボードフォーカスがListBox
に戻った場合(または、行ったままになった場合は、すぐに戻ってきます)、正しいアイテムのキーボードフォーカスは期待どおりになります。
この問題を示すサンプルコードを次に示します。これをデモするには、コードを実行し、マウスを使用してリストで「7」を選択し(したがって、ListBox
にフォーカスを置きます)、「テスト」ボタンをクリックします。最後に、キーボードの「Alt」キーをタップして、フォーカス四角形を表示します。実際にはまだ「7」にあり、上矢印と下矢印を使用する場合、ユーザーが期待する「4」ではなく、その行に相対的です。
ボタンを押すときにフォーカスのリストボックスを奪わないように、ボタンのFocusable
をfalse
に設定していることに注意してください。これがない場合、ボタンをクリックするとListBox
がフォーカスを失います。したがって、フォーカスがListBoxに戻ると、正しいアイテムになります。
XAMLファイル:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
Width="525" Height="350" WindowStartupLocation="CenterScreen"
Title="MainWindow" x:Name="Root">
<DockPanel>
<Button Content="Test"
DockPanel.Dock="Bottom"
HorizontalAlignment="Left"
Focusable="False"
Click="Button_Click" />
<ListBox x:Name="MainListBox" />
</DockPanel>
</Window>
コードビハインド:
using System.Collections.ObjectModel;
using System.Windows;
namespace Test
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainListBox.ItemsSource = new string[]{
"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"
};
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MainListBox.SelectedItem = MainListBox.Items[3];
}
}
}
注:一部のユーザーはIsSynchronizedWithCurrentItem
の使用を提案していますが、そのプロパティはSelectedItem
のListBox
を関連ビューのCurrent
プロパティと同期します。この問題はまだ存在するため、フォーカスとは関係ありません。
回避策は、一時的に別の場所にフォーカスを設定し、選択したアイテムを設定し、ListBox
にフォーカスを戻すことですが、これはViewModel
を作成しなければならないという望ましくない効果があります。 ListBox
自体を認識してから、フォーカスがあるかどうかなどに応じてロジックを実行します(つまり、「他の場所にフォーカスしてから、ここに戻った場合はここに戻ってきます」とは言いたくないでしょう) tを他の場所から盗むので、すでにフォーカスがあります。)さらに、宣言型バインディングを介してこれを単純に処理することはできません。言うまでもなく、これはいです。
それからまた、「ugい」船、それがあります。
数行のコードです。コードビハインドで使用したくない場合は、添付の動作でパッケージ化できると確信しています。
private void Button_Click(object sender, RoutedEventArgs e)
{
MainListBox.SelectedItem = MainListBox.Items[3];
MainListBox.UpdateLayout(); // Pre-generates item containers
var listBoxItem = (ListBoxItem) MainListBox
.ItemContainerGenerator
.ContainerFromItem(MainListBox.SelectedItem);
listBoxItem.Focus();
}
おそらく動作が添付されていますか?何かのようなもの
public static DependencyProperty FocusWhenSelectedProperty = DependencyProperty.RegisterAttached(
"FocusWhenSelected",
typeof(bool),
typeof(FocusWhenSelectedBehavior),
new PropertyMetadata(false, new PropertyChangedCallback(OnFocusWhenSelectedChanged)));
private static void OnFocusWhenSelectedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var i = (ListBoxItem)obj;
if ((bool)args.NewValue)
i.Selected += i_Selected;
else
i.Selected -= i_Selected;
}
static void i_Selected(object sender, RoutedEventArgs e)
{
((ListBoxItem)sender).Focus();
}
およびxamlで
<Style TargetType="ListBoxItem">
<Setter Property="local:FocusWhenSelectedBehavior.FocusWhenSelected" Value="True"/>
</Style>
XAMLでこれを試しましたが、うまくいきませんでしたか?
<ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=YourCollectionView}" SelectedItem="{Binding SelectedItem}"></ListBox>
SelectedItem
プロパティ:
private YourObject _SelectedItem;
public YourObject SelectedItem
{
get
{
return _SelectedItem;
}
set
{
if (_SelectedItem == value)
return;
_SelectedItem = value;
OnPropertyChanged("SelectedItem");
}
}
これで、コードで次のことができます。
SelectedItem = theItemYouWant;
私にとって、このアプローチは常に機能します。
最初) ListBox.Items.IndexOf()でリストボックス内の選択されたアイテムを見つける必要があります。
Second) ListBox.SelectedItems.Add()でアイテムを追加します。
これは私のコードです:
DataRow[] drWidgetItem = dtItemPrice.Select(widgetItemsFilter);
lbxWidgetItem.SelectedItems.Clear(); foreach(DataRow drvItem in
drWidgetItem)
lbxWidgetItem.SelectedItems.Add(lbxWidgetItem.Items[dtItemPrice.Rows.IndexOf(drvItem)]);
リストボックスで項目を選択したい場合は、この方法を使用できます:
ListBox.SelectedItem =(Your ListBoxItem);
ListBoxでいくつかの項目を選択する場合は、この方法を使用する必要があります:
ListBox.SelectedItems.Add(Your ListBoxItem);
ListBox.SelectedItemを使用してから、ListBox.ScrollIntoView(listBox.SelectedItem)を使用するだけです。
サンプルコード:
private void textBox2_TextChanged(object sender, TextChangedEventArgs e)
{
var comparision = StringComparison.InvariantCultureIgnoreCase;
string myString = textBox2.Text;
List<dynamic> index = listBox.Items.SourceCollection.OfType<dynamic>().Where(x=>x.Nombre.StartsWith(myString,comparision)).ToList();
if (index.Count > 0) {
listBox.SelectedItem= index.First();
listBox.ScrollIntoView(listBox.SelectedItem);
}
}