2010-02-03 15 views
6

He añadido un DataTemplate a una clase ListBox para unirse a mi colección:Seleccionar ListBoxItem si Cuadro de texto en ItemTemplate obtiene foco

<ListBox x:Name="lstEmails" Height="259" Margin="12,0,12,41" Width="276" 
     SelectionChanged="lstEmails_SelectionChanged"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal"> 
       <Label Visibility="Hidden" Content="{Binding ID}"></Label> 
       <TextBox Width="200" Text="{Binding EmailAddress}"></TextBox> 
      </StackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Esto hace exactamente lo que yo quiero que haga. Aunque cuando hago clic en TextBox, ListBox no establece automáticamente el ListItem asociado como Selected. Podría hacer esto en código, pero preferiría usar esto como un componente (no hay sorpresas allí).

¿Alguna idea sobre cómo lograr esto?


Eso no parece funcionar, no me deja hacer clic en nada. Me he perdido algo Aquí está mi nuevo XAML.

<UserControl.Resources> 
    <!--<TextBox x:Key="TB" x:Name="TextBoxInsideListBoxItemTemplate"> 
     <TextBox.Style>--> 
      <Style TargetType="{x:Type TextBox}"> 
       <Setter Property="IsHitTestVisible" Value="False" /> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}" 
                Value="True"> 
         <Setter Property="IsHitTestVisible" Value="True" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     <!--</TextBox.Style> 
    </TextBox>--> 
</UserControl.Resources> 
<Grid> 
    <ListBox x:Name="lstEmails" Height="259" Margin="12,0,12,41" Width="276" SelectionChanged="lstEmails_SelectionChanged"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <!--<Label Visibility="Hidden" Content="{Binding ID}"></Label>--> 
        <TextBox Width="220" Text="{Binding EmailAddress}" > 
        </TextBox> 
        <!--<TextBox Width="220" Text="{Binding EmailAddress}" GotFocus="TextBox_GotFocus"></TextBox>--> 
       </StackPanel> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <Button Width="20" Margin="12,0,0,12" Name="btnAdd" VerticalAlignment="Bottom" Click="btnAdd_Click" Height="23" HorizontalAlignment="Left">+</Button> 
    <Button Width="20" HorizontalAlignment="Left" Margin="30,0,0,12" Name="btnRemove" VerticalAlignment="Bottom" Click="btnRemove_Click" Height="23">-</Button> 
    <Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,12" Name="btnApply" VerticalAlignment="Bottom" Width="49" Click="btnApply_Click">Apply</Button> 
</Grid> 

Creo que el clic dos veces es buena funcionalidad.

Respuesta

3

Si tiene varias instancias de ListBox, entonces puede considerar usar su cuadro de lista personalizado (derivandolo de ListBox). Ver the explanation here.


O bien, utilizar este piratear si tiene sólo 1 (o sólo una pequeña cantidad de) tales ListBox y no quieren crear una clase separada para que:

<TextBox x:Name="TextBoxInsideListBoxItemTemplate" ... > 

    <TextBox.Style> 
     <Style TargetType="{x:Type TextBox}"> 
      <Setter Property="IsHitTestVisible" Value="False" /> 
      <Style.Triggers> 
       <DataTrigger 
         Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, 
        AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}" 
         Value="True"> 
        <Setter Property="IsHitTestVisible" Value="True" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </TextBox.Style> 

</TextBox> 

Tenga en cuenta que Tendrás que hacer clic una vez más para editar el texto en el TextBox (que en realidad es genial según yo).

7

Puede desencadenar en la propiedad IsKeyboardFocusWithin en ItemContainerStyle y establecer IsSelected en true.

<ListBox.ItemContainerStyle> 
    <Style TargetType="{x:Type ListBoxItem}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True"> 
       <DataTrigger.EnterActions> 
        <BeginStoryboard> 
         <Storyboard> 
          <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)"> 
           <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/> 
          </BooleanAnimationUsingKeyFrames> 
         </Storyboard> 
        </BeginStoryboard> 
       </DataTrigger.EnterActions> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</ListBox.ItemContainerStyle> 

Usted podría también utilizar un Setter en lugar de una única animación fotograma, pero entonces la selección se perderán una vez que el enfoque deja la ListBox:

<ListBox.ItemContainerStyle> 
    <Style TargetType="{x:Type ListBoxItem}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True"> 
       <Setter Property="IsSelected" Value="True"/> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</ListBox.ItemContainerStyle> 
+0

Brilliant! Me salvó hoy! –

+0

Esta es una gran solución, excepto que no se combina bien con los modos de selección Extendido y Múltiple. – xvpower

0

tuve una situación en la que la selección de una El elemento listbox cambiaría su diseño, por lo que el control podría haberse alejado del cursor antes de que se suelte el botón del mouse. No he encontrado una solución mejor que utilizar un ligero retraso en el guión gráfico si quiero mantener todo en xaml.

Más importante aún, GotKeyboardFocus parece funcionar mejor que IsKeyboardFocusWithin para las selecciones repetidas.

<EventTrigger RoutedEvent="GotKeyboardFocus"> 
    <BeginStoryboard> 
     <Storyboard> 
      <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected"> 
       <DiscreteBooleanKeyFrame KeyTime="00:00:00.3" Value="True"/> 
      </BooleanAnimationUsingKeyFrames> 
     </Storyboard> 
    </BeginStoryboard> 
</EventTrigger> 
Cuestiones relacionadas