wpf listbox selecteditem

¿Cómo se establece programáticamente el foco en SelectedItem en un WPF ListBox que ya tiene foco?



(5)

En tu XAML, ¿has probado esto y no has funcionado?

<ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=YourCollectionView}" SelectedItem="{Binding SelectedItem}"></ListBox>

Y la propiedad SelectedItem :

private YourObject _SelectedItem; public YourObject SelectedItem { get { return _SelectedItem; } set { if (_SelectedItem == value) return; _SelectedItem = value; OnPropertyChanged("SelectedItem"); } }

Ahora en tu código puedes hacer:

SelectedItem = theItemYouWant;

Para mí, este enfoque funciona siempre.

Queremos establecer el elemento SelectedItem de un ListBox programáticamente y queremos que ese elemento tenga un foco para que las teclas de flecha funcionen en relación con ese elemento seleccionado. Parece lo suficientemente simple.

Sin embargo, el problema es que si el ListBox ya tiene el foco del teclado al establecer SelectedItem programación, mientras actualiza correctamente la propiedad IsSelected en el ListBoxItem , no establece el foco del teclado en él y, por lo tanto, las teclas de flecha se mueven con respecto al anterior. elemento enfocado en la lista y no el elemento recién seleccionado como uno esperaría.

Esto es muy confuso para el usuario, ya que hace que la selección parezca saltar cuando se utiliza el teclado, ya que vuelve a estar donde estaba antes de que se llevara a cabo la selección programática.

Nota: Como dije, esto solo ocurre si establece programáticamente la propiedad SelectedItem en un ListBox que ya tiene el foco del teclado. Si no lo hace (o si lo hace pero te vas, luego regresa), cuando el foco del teclado regrese al ListBox , el elemento correcto ahora tendrá el foco del teclado como se esperaba.

Aquí hay un código de muestra que muestra este problema. Para hacer una demostración de esto, ejecute el código, use el mouse para seleccionar ''Siete'' en la lista (poniendo así el foco en el ListBox ), luego haga clic en el botón ''Prueba''. Finalmente, toque la tecla ''Alt'' en su teclado para revelar el foco rect. Verás que todavía está en ''Siete'' y si utilizas las flechas hacia arriba y hacia abajo, están relacionadas con esa fila, no con ''Cuatro'' como esperaría un usuario.

Tenga en cuenta que Focusable configurado en false en el botón como para no robar el cuadro de lista de enfoque al presionarlo. Si no tuviera esto, el ListBox perdería el foco cuando haga clic en el botón, y así, cuando el foco volviera al ListBox, estaría en el elemento correcto.

Archivo 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>

Código detrás:

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]; } } }

Nota: Algunos han sugerido utilizar IsSynchronizedWithCurrentItem , pero esa propiedad sincroniza el SelectedItem del ListBox con la propiedad Current de la vista asociada. No está relacionado con el enfoque ya que este problema aún existe.

Nuestra solución es establecer temporalmente el foco en otro lugar, luego establecer el elemento seleccionado, luego establecer el foco nuevamente en el ListBox pero esto tiene el efecto indeseable de tener que hacer que nuestro ViewModel consciente del ListBox sí mismo, luego realizar la lógica dependiendo sobre si tiene o no el foco, etc. (es decir, no querría decir simplemente ''Enfóquese en otro lado y vuelva aquí, si'' aquí ''no tuviera el enfoque ya que lo robaría de otro lado). ) Además, no puedes simplemente manejar esto a través de enlaces declarativos. No hace falta decir que esto es feo.

Por otra parte, naves ''feos'', entonces eso es todo.


Solo necesita usar ListBox.SelectedItem y luego usar ListBox.ScrollIntoView (listBox.SelectedItem)

Código de ejemplo:

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); } }


Son un par de líneas de código. Si no lo quería en código subyacente, estoy seguro de que podría estar empaquetado en un comportamiento adjunto.

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(); }


Tal vez con un comportamiento adjunto? Algo como

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(); }

y en xaml

<Style TargetType="ListBoxItem"> <Setter Property="local:FocusWhenSelectedBehavior.FocusWhenSelected" Value="True"/> </Style>


Primero) Debe encontrar los elementos seleccionados en el cuadro de lista con ListBox.Items.IndexOf ().
Segundo) Ahora agregue elementos con ListBox.SelectedItems.Add ().

Este es mi código:

DataRow[] drWidgetItem = dtItemPrice.Select(widgetItemsFilter); lbxWidgetItem.SelectedItems.Clear(); foreach(DataRow drvItem in drWidgetItem) lbxWidgetItem.SelectedItems.Add(lbxWidgetItem.Items[dtItemPrice.Rows.IndexOf(drvItem)]);

Si desea seleccionar un elemento en ListBox, puede usarlo de esta manera:
ListBox.SelectedItem = (Your ListBoxItem);

Si desea seleccionar algunos elementos en ListBox, debe usar esta opción:
ListBox.SelectedItems.Add (Your ListBoxItem);