wpf xaml listbox datatemplate triggers

wpf - Seleccionar un ListBoxItem cuando su ComboBox interno está enfocado



xaml datatemplate (3)

Tengo un DataTemplate que será un ListBoxItem con plantilla, este DataTemplate tiene un ComboBox que, cuando tiene foco, quiero que se seleccione el ListBoxItem que representa esta plantilla, esto me parece a mí. pero, por desgracia, no funciona = (

Entonces, la verdadera pregunta aquí es dentro de un DataTemplate ¿es posible obtener o establecer el valor de la propiedad ListBoxItem.IsSelected través de un DataTemplate.Trigger ?

<DataTemplate x:Key="myDataTemplate" DataType="{x:Type local:myTemplateItem}"> <Grid x:Name="_LayoutRoot"> <ComboBox x:Name="testComboBox" /> </Grid> <DataTemplate.Triggers> <Trigger Property="IsFocused" value="true" SourceName="testComboBox"> <Setter Property="ListBoxItem.IsSelected" Value="true" /> </Trigger> </DataTemplate.Triggers> </DataTemplate> <ListBox ItemTemplate="{StaticResource myDataTemplate}" />


Descubrí que prefería usar esto:

<Style TargetType="ListBoxItem"> <Style.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="True"> <Setter Property="IsSelected" Value="True"></Setter> </Trigger> </Style.Triggers> </Style>

Simple y funciona para todos los elementos de cuadro de lista, independientemente de lo que hay dentro.


Encontré una solución para tu problema.

El problema es que cuando tiene un control en su elemento de cuadro de lista, y se hace clic en el control (como para ingresar texto o cambiar el valor de un cuadro combinado), ListBoxItem no se selecciona.

Esto debería hacer el trabajo:

public class FocusableListBox : ListBox { protected override bool IsItemItsOwnContainerOverride(object item) { return (item is FocusableListBoxItem); } protected override System.Windows.DependencyObject GetContainerForItemOverride() { return new FocusableListBoxItem(); } }

-> Use este FocusableListBox en lugar del ListBox predeterminado de WPF.

Y use este ListBoxItem:

public class FocusableListBoxItem : ListBoxItem { public FocusableListBoxItem() { GotFocus += new RoutedEventHandler(FocusableListBoxItem_GotFocus); } void FocusableListBoxItem_GotFocus(object sender, RoutedEventArgs e) { object obj = ParentListBox.ItemContainerGenerator.ItemFromContainer(this); ParentListBox.SelectedItem = obj; } private ListBox ParentListBox { get { return (ItemsControl.ItemsControlFromItemContainer(this) as ListBox); } } }

Un Treeview también tiene este problema, pero esta solución no funciona para Treeview , porque SelectedItem de Treeview es de readonly . Entonces, si me pueden ayudar con Treeview, por favor ;-)


No tengo idea de por qué tu gatillo no funciona. Para capturar el evento get focus del cuadro combinado (o cualquier control dentro de un elemento de cuadro de lista) puede usar eventos enrutados adjuntos. También puede poner el código en un cuadro de lista derivado si necesita este comportamiento en otras partes de su aplicación.

XAML:

<Window x:Class="RoutedEventDemo.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Specialized="clr-namespace:System.Collections.Specialized;assembly=System" xmlns:System="clr-namespace:System;assembly=mscorlib" Height="300" Width="300"> <Window.Resources> <DataTemplate x:Key="myDataTemplate"> <Grid> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding}" Margin="5,0"/> <ComboBox Width="50"> <ComboBoxItem>AAA</ComboBoxItem> <ComboBoxItem>BBB</ComboBoxItem> </ComboBox> </StackPanel> </Grid> </DataTemplate> </Window.Resources> <Grid> <ListBox ItemTemplate="{StaticResource myDataTemplate}"> <ListBox.ItemsSource> <Specialized:StringCollection> <System:String>Item 1</System:String> <System:String>Item 2</System:String> <System:String>Item 3</System:String> </Specialized:StringCollection> </ListBox.ItemsSource> </ListBox> </Grid> </Window>

El código detrás de la conexión a todos los eventos de foco.

using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace RoutedEventDemo { public partial class Window1 : Window { public Window1() { InitializeComponent(); EventManager.RegisterClassHandler(typeof(UIElement), GotFocusEvent, new RoutedEventHandler(OnGotFocus)); } private static void OnGotFocus(object sender, RoutedEventArgs e) { // Check if element that got focus is contained by a listboxitem and // in that case selected the listboxitem. DependencyObject parent = e.OriginalSource as DependencyObject; while (parent != null) { ListBoxItem clickedOnItem = parent as ListBoxItem; if (clickedOnItem != null) { clickedOnItem.IsSelected = true; return; } parent = VisualTreeHelper.GetParent(parent); } } } }