2009-09-22 18 views
11

Tengo un DataTemplate que será un ListBoxItem con plantilla, esta DataTemplate tiene un ComboBox en ella que cuando se tiene el foco Quiero que el ListBoxItem que esta plantilla representa para convertirse seleccionada, esta me parece bien pero lamentablemente no funciona = (Selección de un ListBoxItem cuando su ComboBox interior está centrado

Así que la pregunta real aquí es dentro de un DataTemplate es posible obtener o establecer el valor de la propiedad ListBoxItem.IsSelected a 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}" /> 

Respuesta

8

encontré una solución para su problema

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

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

-> Utilice esta FocusableListBox en lugar del cuadro de lista por defecto de WPF.

Y utilizar 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, presenta este problema, pero esta solución no funciona para un Treeview, porque SelectedItem de Treeview es readonly. Así que si me pueden ayudar con TreeView por favor ;-)

+1

Ha solucionado mi problema. en realidad estaba bastante perplejo en este caso. enfoque interesante para la solución. Tengo curiosidad por saber si hay una forma de hacerlo en XAML. – AppleDrink

+0

no tengo idea si es posible en xaml. Me alegra que solo funcione en el código :) – Natrium

0

No tengo idea de por qué su 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> 

Código detrás de conectar a todos los eventos Focus consiguió.

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

descubrí que prefiero 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 listboxitems, independientemente de lo que hay dentro.

+0

Tu respuesta fue útil cada vez que tengo este problema. Pero ahora tengo un botón Eliminar en ListBoxItem que es Focusable = False. En este caso, al hacer clic en este botón, se elimina el antiguo SelectedItem en lugar de seleccionar el elemento en el que se hizo clic en Eliminar y luego eliminarlo. – Vishal

+1

Su respuesta funciona, pero después de hacer clic en un botón o en cualquier otro control mi índice seleccionado se restablece en -1 – Decoder94

Cuestiones relacionadas