Windows 8 : GridView et ListView au contenu adapté

 

Lorsque l’on travaille sur une application Windows Store, il est courant d'avoir à afficher des collections d'information.

Petit rappel sur les contrôles

Un type de contrôle que l’on utilise alors hérite d’ItemsControl. A partir du moment où l’on veut se binder sur une collection, c’est la solution pour l’affichage des données.

Mais à l’heure des tablettes et des nouveaux devices qui arrivent tous les jours, qui ont des résolutions différente et surtout, car c’est ce qui importe pour les applications Windows Store, des diagonales d’écran variées, il est de bon ton de bien adapter ses designs à ces tailles distinctes.

Les contrôles permettant la sélection d’Item fréquemment utilisés sont la ListView et la GridView qui ont pour points communs :

  • D’hériter de ItemsControl
  • De permettre de grouper les items
  • De supporter l’affichage des elements dans des VirtualizingPanel
  • D’autoriser différents mode de sélection

Du coté de leurs divergences :

  • Par défaut, la ListView affiche ses éléments verticalement (et est souvent utilisée dans la snapped view)
    1: <ListView Background="Red" ItemsSource="{Binding MyCollection}"  >
    2:     <ListView.ItemTemplate>
    3:         <DataTemplate>
    4:             <Button Content="{Binding}" Background="Blue"/>
    5:         </DataTemplate>
    6:     </ListView.ItemTemplate>
    7: </ListView>

1-ListView

  • alors que la GridView les affichera de la même manière mais en gérant un « wrapping » qui une fois la hauteur de la GridView atteinte affiches les items suivants à la suite horizontalement.
    1: <GridView Background="Red" ItemsSource="{Binding MyCollection}"  >
    2:     <GridView.ItemTemplate>
    3:         <DataTemplate>
    4:             <Button Content="{Binding}" Background="Blue"/>
    5:         </DataTemplate>
    6:     </GridView.ItemTemplate>
    7: </GridView>

2-GridView

Les conteneurs d’items (ou ItemsPanel)

Pour ces deux contrôles, il est bien sûr possible de changer les conteneurs (ItemsPanel) par défaut qui sont, pour la GridView, la WrapGrid et pour la ListView, le VirtualizingStackPanel par un contrôle héritant de Panel. Un cas souvent rencontré serait, par exemple, pour une GridView, de choisir un StackPanel (Virtualisable ou non) avec une orientation horizontale afin de n’avoir qu’un élément par colonnes. Malheureusement, un problème fréquent est que le contenu de l’élément ne prend alors pas tout l’espace vertical (dans ce cas) disponible. Et ce, même en précisant que le VerticalAlignment="Stretch" sur le Button du DataTemplate.



    1: <GridView Grid.Row="1" Height="120" VerticalAlignment="Top" Grid.Column="3" Margin="30,0,30,20" Background="Red" ItemsSource="{Binding MyCollection}"  >
    2:     <GridView.ItemsPanel>
    3:         <ItemsPanelTemplate>
    4:             <StackPanel Orientation="Horizontal"/>
    5:         </ItemsPanelTemplate>
    6:     </GridView.ItemsPanel>
    7:     <GridView.ItemTemplate>
    8:         <DataTemplate>
    9:             <Button VerticalAlignment="Stretch" Content="{Binding}" Background="Blue"/>
   10:         </DataTemplate>
   11:     </GridView.ItemTemplate>
   12: </GridView>


3-GridView with StackPanel Horizontal

Une solution

Pour que notre contrôle prenne bien toute la hauteur, la solution est de ne pas oublier que notre StackPanel ne donnera à notre DataTemplate de notre ItemTemplate que la place qu’il nécessite. Mais ce fameux Button de notre DataTemplate, est lui-même contenu dans un ItemContainer qui est, dans le cas de la GridView, un GridViewItem et un ListViewItem pour la ListView. Et cet ItemContainer à comme valeur par défaut pour son VerticalContentAlignment : Top et pour son HorizontalContentAlignment : Left.

Donc il convient de modifier les ContentAlignment de l’ItemContainerStyle de notre contrôle en Stretch et comme par magie, notre Button s’agrandit comme recherché. A noter qu’il est préférable de bien vérifier que le contrôle contenu dans le DataTemplate est en Stretch sur la dimension qui nous intéresse.

Donc ici, la solution se résume à spécifier dans l’ItemContainerStyle de notre GridView ou de notre ListView un VerticalContentAlignment="Stretch"

Pour la ListView, voici le code XAML

    1: <ListView  VerticalAlignment="Top" Background="Red" ItemsSource="{Binding MyCollection}"  >
    2:     <ListView.ItemContainerStyle>
    3:         <Style TargetType="ListViewItem" >
    4:             <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    5:         </Style>
    6:     </ListView.ItemContainerStyle>
    7:     <ListView.ItemTemplate>
    8:         <DataTemplate>
    9:             <Button HorizontalAlignment="Stretch" Content="{Binding}" Background="Blue"/>
   10:         </DataTemplate>
   11:     </ListView.ItemTemplate>
   12: </ListView>

et le rendu visuel

4-ListView Filled

La même chose pour une GridView

    1: <GridView  VerticalAlignment="Top"  Background="Red" ItemsSource="{Binding MyCollection}"  >    <GridView.ItemContainerStyle>
    2:         <Style TargetType="GridViewItem" >
    3:             <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    4:         </Style>
    5:     </GridView.ItemContainerStyle>
    6:     <GridView.ItemsPanel>
    7:         <ItemsPanelTemplate>
    8:             <StackPanel Orientation="Horizontal"/>
    9:         </ItemsPanelTemplate>
   10:     </GridView.ItemsPanel>
   11:     <GridView.ItemTemplate>
   12:         <DataTemplate>
   13:             <Button VerticalAlignment="Stretch" Content="{Binding}" Background="Blue"/>
   14:         </DataTemplate>
   15:     </GridView.ItemTemplate>
   16: </GridView>

5-GridView with StackPanel Horizontal Filled

Code Source

Le code source de la démo se trouve ici.

 

- David ROZEN -