Cambiar el DataTemplate de un ListBox con DataTrigger

En el anterior post Sergi se dio cuenta que era mejor realizar el cambio del DataTemplate a través de un DataTrigger, en el anterior el cambio del DataTemplate en el ListBox se realizaba a través del evento SelectionChanged y la propiedad ItemTemplateSelector había un problema que detecto Julio y es que se producía un comportamiento raro con las teclas de subir y bajar, realmente no funcionaba bien.

Ele ejemplo lo puse porque cuando vienes del desarrollo tradicional lo primero que piensas es en hacer todo con eventos como hacíamos con WinForms, pero ahora con WPF tenemos que cambiar de mentalidad y aprovecharnos de toda la potencia del XAML, en este caso con DataTriggers.

Para enseñarlo no voy a utilizar el ejemplo del anterior post sino un nuevo ejemplo con dos listas una con SelectionChanged y la otra con DataTrigger, el otro ejemplo lo dejo para que lo cambies vosotros a modo de ejercicio.

La aplicación es fea, habría que cambiarla con MultiBinding… solo quiero demostrar lo de este post

 

image

En este caso el XAML de los DataTemplates de SelectionChanged es

 

 

 <DataTemplate x:Key="PeopleTemplateSimple">
            <StackPanel Orientation="Horizontal" Background="AliceBlue">
                <TextBlock Text="{Binding Path=FirstName}"/>
                <TextBlock Text="{Binding Path=LastName}"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="PeopleTemplateComplex">
            <Border BorderBrush="#FFE7FF12" BorderThickness="5,0,5,0" CornerRadius="5,5,5,5" Width="Auto" Height="61.34" Margin="0,0,0,10">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.02,0.5" StartPoint="0.982,0.5">
                        <GradientStop Color="#FF5C3610" Offset="0"/>
                        <GradientStop Color="#FFC88848" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>
                <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.39*"/>
                        <ColumnDefinition Width="0.61*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="0.343*"/>
                        <RowDefinition Height="0.327*"/>
                        <RowDefinition Height="0.33*"/>
                    </Grid.RowDefinitions>
                    <TextBlock Margin="0,0,4,0" Text="Nombre Completo" TextWrapping="Wrap" HorizontalAlignment="Right" VerticalAlignment="Center"/>
                    <TextBlock Margin="0,0,4,0" Grid.Row="1" Text="SSN" TextWrapping="Wrap" HorizontalAlignment="Right" VerticalAlignment="Center"/>
                    <TextBlock HorizontalAlignment="Right" Margin="0,1.951,4,2.331" VerticalAlignment="Stretch" Text="Fecha" TextWrapping="Wrap" Grid.Row="2" d:LayoutOverrides="Height"/>
                    <TextBlock Grid.Column="1" Text="{Binding Path=FirstName, Mode=Default}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Path=SSN, Mode=Default}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    <TextBlock Grid.Column="1" Grid.Row="2" Text="{Binding Path=DateOfBirth, Mode=Default}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                </Grid>
            </Border>
        </DataTemplate>

Como en el anterior post, dos DataTemplates uno para el item sin selección y otro mas completo para el item seleccionado

El DataTemplate para el DataTrigger es

 

 

<ControlTemplate x:Key="PeopleTemplateSimple2">
            <StackPanel Orientation="Horizontal" Background="AliceBlue">
                <TextBlock Text="{Binding Path=FirstName}"/>
                <TextBlock Text="{Binding Path=LastName}"/>
            </StackPanel>
        </ControlTemplate>

        <ControlTemplate x:Key="PeopleTemplateComplex2">
            <Border BorderBrush="#FFE7FF12" BorderThickness="5,0,5,0" CornerRadius="5,5,5,5" Width="Auto" Height="61.34" Margin="0,0,0,10">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.02,0.5" StartPoint="0.982,0.5">
                        <GradientStop Color="#FF5C3610" Offset="0"/>
                        <GradientStop Color="#FFC88848" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>
                <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.39*"/>
                        <ColumnDefinition Width="0.61*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="0.343*"/>
                        <RowDefinition Height="0.327*"/>
                        <RowDefinition Height="0.33*"/>
                    </Grid.RowDefinitions>
                    <TextBlock Margin="0,0,4,0" Text="Nombre Completo" TextWrapping="Wrap" HorizontalAlignment="Right" VerticalAlignment="Center"/>
                    <TextBlock Margin="0,0,4,0" Grid.Row="1" Text="SSN" TextWrapping="Wrap" HorizontalAlignment="Right" VerticalAlignment="Center"/>
                    <TextBlock HorizontalAlignment="Right" Margin="0,1.951,4,2.331" VerticalAlignment="Stretch" Text="Fecha" TextWrapping="Wrap" Grid.Row="2" d:LayoutOverrides="Height"/>
                    <TextBlock Grid.Column="1" Text="{Binding Path=FirstName, Mode=Default}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Path=SSN, Mode=Default}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    <TextBlock Grid.Column="1" Grid.Row="2" Text="{Binding Path=DateOfBirth, Mode=Default}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                </Grid>
            </Border>
        </ControlTemplate>

Lo mismo pero en este caso cambiamos el DataTemplate por ControlTemplate que permite cambiar la plantilla visual de un control de WPF, es decir de cualquier control que herede de Control, que es donde está definida la propiedad Template

Para nuestro caso hacemos el DataTemplate

 <DataTemplate x:Key="PeopleTemplateUsingTriggers">
            <Control x:Name="theControl" Focusable="False" Template="{StaticResource PeopleTemplateSimple2}" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
                    <Setter TargetName="theControl" Property="Template" Value="{StaticResource PeopleTemplateComplex2}" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>

Si os fijáis tenemos un control al cual le aplicamos el Template simple, pero tenemos un DataTrigger que enlazamos con el Item de la lista y la propiedad IsSelected del item, si es true cambiamos el Template del control por el complejo, bastante mas sencillo y eficaz que subscribirnos al evento SelectionChanged

Por ultimo la lista quedaría

 

 <ListBox Margin="0,10,0,0" x:Name="PeopleListBox2"  Background="#FFF9F0C3" 
                 ItemsSource="{Binding Path=People, Mode=Default}" 
                 ItemTemplate="{StaticResource PeopleTemplateUsingTriggers}" Height="300" />

La conclusión que tenemos que sacar es que al cambiarnos a WPF debemos de sacar el máximo rendimiento al XAML y olvidarnos un poco de la manera de programa WinForms, os animo a que hagáis el ejemplo del post anterior

3 comentarios sobre “Cambiar el DataTemplate de un ListBox con DataTrigger”

  1. Yo hace muchios años en los tiempos de W95 me imaginé que sería útil disponer de datatiggers o acciones acordes a los datos de forma declarativa.

    Siempre que al cabo de un tiempo tus ideas se hacen realidad te dá un subidón al ver que ibas por buen camino!!!!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *