it-swarm-es.tech

Cambie WPF DataTemplate para el elemento ListBox si se selecciona

Necesito cambiar el DataTemplate para los elementos en un ListBox dependiendo de si el elemento está seleccionado o no (mostrando información diferente/más cuando se selecciona).

No obtengo un evento GotFocus/LostFocus en el elemento más alto de la plantilla de datos (un StackPanel) al hacer clic en el elemento ListBox en cuestión (solo a través de tabulaciones), y no tengo más ideas.

88
Daniel Beck

La forma más fácil de hacer esto es proporcionar una plantilla para el "ItemContainerStyle" y NO la propiedad "ItemTemplate". En el siguiente código, creo 2 plantillas de datos: una para los estados "no seleccionados" y otra para los estados "seleccionados". Luego creo una plantilla para el "ItemContainerStyle" que es el "ListBoxItem" real que contiene el elemento. Establecí la "Plantilla de contenido" predeterminada en el estado "No seleccionado", y luego proporcioné un desencadenante que intercambia la plantilla cuando la propiedad "IsSelected" es verdadera. (Nota: estoy configurando la propiedad "ItemsSource" en el código detrás de una lista de cadenas para simplificar)

<Window.Resources>

<DataTemplate x:Key="ItemTemplate">
    <TextBlock Text="{Binding}" Foreground="Red" />
</DataTemplate>

<DataTemplate x:Key="SelectedTemplate">
    <TextBlock Text="{Binding}" Foreground="White" />
</DataTemplate>

<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
    <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

</Window.Resources>
<ListBox x:Name="lstItems" ItemContainerStyle="{StaticResource ContainerStyle}" />
173
Micah

Para configurar el estilo cuando se selecciona el elemento o no todo lo que necesita hacer es recuperar el padre ListBoxItem en su <DataTemplate> y el estilo de activación cambia cuando cambia IsSelected. Por ejemplo, el siguiente código creará una TextBlock con el color predeterminado de Foreground verde. Ahora, si el elemento se selecciona, la fuente cambiará. rojo y cuando el ratón esté sobre el elemento girará amarillo. De esa manera, no necesita especificar plantillas de datos separadas como se sugiere en otras respuestas para cada estado que desee cambiar ligeramente.

<DataTemplate x:Key="SimpleDataTemplate">
    <TextBlock Text="{Binding}">
        <TextBlock.Style>
            <Style>
                <Setter Property="TextBlock.Foreground" Value="Green"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Red"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Yellow"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</DataTemplate>
7
Darien Pardinas

También se debe tener en cuenta que el panel de la pila no es focalizable, por lo que nunca se enfocará (establezca Enfocable = Verdadero si usted/realmente/quiere enfocarlo). Sin embargo, la clave para recordar en situaciones como esta es que el Panel de pila es child del TreeViewItem, que es el ItemContainer en este caso. Como sugiere Micah, ajustar el ítem de contenedor es un buen enfoque.

Probablemente podría hacerlo usando DataTemplates, y cosas tales como datatriggers que usarían la extensión de marcado RelativeSouce para buscar el listviewitem

6
Dominic Hopton