En WPF, il est possible d’avoir une ListView pour afficher une liste d’élément. Voilà un exemple d’une ListView avec son style par défaut :
Voilà le code pour cela :
<ListView ItemsSource="{Binding List}"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" VerticalAlignment="Center" /> </DataTemplate> </ListView.ItemTemplate> </ListView>
J’ai un ViewModel dans lequel se trouve une propriété :
public List<string> List { get; set; }
Le but de cet article est de supprimer trois choses :
- Le fond bleu de l’élément sélectionné
- La bordure bleue de l’élément sélectionné
- La ligne en pointillé qui apparait lors de l’utilisation de la touche tabulation du clavier
Réflexion et tests
Dans un premier temps on pourrait croire que c’est simple et qu’il suffit de modifier la propriété Background du ListViewItem. Pour ce faire on crée un style qu’on applique à tout les ListViewItem, dans lequel on change la valeur du Background :
<ListView ItemsSource="{Binding List}"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" VerticalAlignment="Center" /> </DataTemplate> </ListView.ItemTemplate> <ListView.Resources> <Style TargetType="{x:Type ListViewItem}" > <Setter Property="Background" Value="LightGreen" /> </Style> </ListView.Resources> </ListView>
Voilà le résultat :
On voit très bien que ce n’est pas ça. Voyons un peu ce qu’un logiciel comme Snoop nous dit :
Là on s’aperçoit que notre ListViewItem est composé d’un border et que lui-même contient un ContentPresenter. Pourtant nous avons bien créé un ItemTemplate et changer la couleur de fond, mais malgré cela, nous nous retrouvons avec un Border que nous n’avons pas créé.
Compréhension
Voyons maintenant les propriétés Background et BorderBrush de ce Border.
Voici les valeurs des propriétés quand la ligne n’est pas sélectionnée :
Voici les valeurs quand la ligne est sélectionnée :
On voit maintenant où sont situé les propriétés que l’on souhaite changer. Modifier ces valeurs n’est pas simple car nous n’ajoutons pas le Border, il est ajouté pas le Framework.
Action
Pour ce faire, nous allons devoir créer un ItemContainerStyle. Dans ce style il faut faire un setter sur la propriété Template. Le template va overrider le style bleu. Puisque nous écrasons le style bleu de l’élément sélectionné, nous allons devoir en recréer un. Pour cela, voici un exemple simple qui s’appuie sur la propriété IsSelected du ListViewItem :
<ListView ItemsSource="{Binding List}" BorderThickness="0" SelectionMode="Single"> <ListView.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListViewItem"> <StackPanel Orientation="Horizontal" Background="Transparent"> <Rectangle x:Name="Point" RadiusX="5" RadiusY="5" Width="10" Height="10" Fill="Black" Visibility="Hidden" /> <ContentPresenter Margin="30,0,30,0" VerticalAlignment="Center" /> </StackPanel> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter TargetName="Point" Property="Visibility" Value="Visible" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListView.ItemContainerStyle> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" VerticalAlignment="Center" /> </DataTemplate> </ListView.ItemTemplate> </ListView>
Ce code nous donne ce résultat :
Pour aller encore plus loin je vous propose de supprimer aussi la ligne en pointillé qui apparait quand on perd le focus de la fenêtre. Rien de plus simple il suffit d’affecter Null à la propriété FocusVisualStyle.
Voilà un code final et le rendu qui va avec :
<Window x:Class="Test.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="200" Height="200"> <Grid> <ListView ItemsSource="{Binding List}" BorderThickness="0" SelectionMode="Single"> <ListView.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListViewItem"> <StackPanel Orientation="Horizontal" Background="Transparent"> <Path x:Name="Left" Visibility="Hidden" Data="M0,9.0583566E-06L13.564999,9.0583566E-06 13.564999,5.0910095 6.1503563,5.0910095 6.1503563,58.909008 13.564999,58.909008 13.564999,64.000008 0,64.000008z" Fill="Blue" Height="30" Width="30" Stretch="Uniform" Canvas.Left="0" /> <ContentPresenter Margin="30,0,30,0" VerticalAlignment="Center" /> <Path x:Name="Right" Visibility="Hidden" Data="M53.978999,0L67.544,0 67.544,64 53.978999,64 53.978999,58.908997 61.39365,58.908997 61.39365,5.0910033 53.978999,5.0910033z" Fill="Blue" Height="30" Width="30" Stretch="Uniform" Canvas.Right="0" /> </StackPanel> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter TargetName="Left" Property="Visibility" Value="Visible" /> <Setter TargetName="Right" Property="Visibility" Value="Visible" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> </Style> </ListView.ItemContainerStyle> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" VerticalAlignment="Center" /> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </Window>