Lisibilité de PanoramaItem et Header de ListBox en WP7

En reprenant une ancienne application utilisant le contrôle panorama, je me suis aperçu combien la suface dédiée à la lecture de l’information était faible par rapport à la taille du titre et sous-titre.

(Zone d’information en rouge)

Pourtant lorque j’utilise le « quoi de neuf » du Hub contact, la sensation n’est plus du tout le même.
En regardant de plus prêt, on découvre que le sous-titre scrolle simplement avec le reste de l’information.
L’information s’étale donc sur une plus grande surface de l’écran


(Zone d’information en rouge)

Comment reproduire cette zone scrollable plus grande ?

Tout d’abord, comme le panoramItem est un control bien fait, si on ne lui mets pas de propriété Header, le sous-titre ne s’affichera pas et ne prendra pas pour autant de place.

Il suffit désormais de créer une ListBox contenant un Header (et pourquoi pas un footer).
On va donc créer ensemble ce controle.

Je profite de la création de ce control pour poser une question à l’équipe VisualStudio chargée des templates d’ajout de nouveaux items : Pourquoi n’est il pas possible intégré simplement un TemplatedControl dans son projet? Il n’y a pas que les UserControls dans la vie.

Bref, On va commencer par créer un projet Windows Phone Panorama.

Puis, on ajoute une classe ListBoxHeaderFooter héritée de ListBox dans un répertoire Controls.

On injecte dans cette classe 4 propriété Dependency (snippet propdp) :

  • Header : Le contenu de l’entête de liste
  • Footer : le contenu de bas de liste Footer
  • HeaderStyle : Le style de l’entête permettant une modification visuelle aisée de celui-ci
  • FooterStyle : Le style du bas de liste permettant une modification visuelle aisée de celui-ci

le constructeur pointera vers un style definit dans le fichier Generic.xaml du repertoire Themes (comme tout TemplatedControl) :

        public ListBoxHeaderFooter()
        {
            this.DefaultStyleKey = typeof(ListBoxHeaderFooter);
        }

A partir de Blend j’ai repris le style d’une ListBox classique en WP7. J’ai rajouté un Grid contenant deux ContentControls (un pour le Header et l’autre pour Footer) en prenant soin de conserver l’ItemPresenter chargé de l’affichage des éléments. Le Scrollviewer encadre le tout.

On retrouve donc dans Generic.xaml le style suivant :

    <Style TargetType="local:ListBoxHeaderFooter">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:ListBoxHeaderFooter">
                    <ScrollViewer x:Name="ScrollViewer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}">

                        <Grid>
                            
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="*"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                            </Grid.RowDefinitions>
                            
                            <ContentControl Grid.Row="0" Content="{TemplateBinding Header}" Style="{TemplateBinding HeaderStyle}"></ContentControl>

                            <ItemsPresenter Grid.Row="1"/>

                            <ContentControl Grid.Row="2" Content="{TemplateBinding Footer}" Style="{TemplateBinding FooterStyle}" ></ContentControl>
                        </Grid>
                    </ScrollViewer>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Les HeaderStyle et FooterStyle sont aussi défini dans ce Style. Le HeaderStyle est calé sur le style de base du Header d’un panoramaItem (style obtenur toujours grace à Blend)

        <Setter Property="HeaderStyle">
            <Setter.Value>
                <Style TargetType="ContentControl">
                    <Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
                    <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeExtraExtraLarge}"></Setter>
                    <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"></Setter>
                    <Setter Property="Margin" Value="10,-27,0,26"></Setter>
                </Style>
            </Setter.Value>
        </Setter>

        <Setter Property="FooterStyle">
            <Setter.Value>
                <Style TargetType="ContentControl">
                    <Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
                    <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeExtraLarge}"></Setter>
                    <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"></Setter>
                    <Setter Property="Margin" Value="12,0,0,0"></Setter>
                </Style>
            </Setter.Value>
        </Setter>

Dans la MainPage.xaml on modifie le Panorama. D’un coté on conserve le PanoramaItem normal avec sa listbox classique, de l’autre le PanoramaItem sans titre contenant notre ListBoxHeaderFooter .

<!--Panorama control-->
<controls:Panorama Title="my application">
 
    <!--Panorama item normal-->
    <controls:PanoramaItem Header="normal" Visibility="Collapsed">

        <ListBox Background="Red" Margin="0,0,-12,0" ItemsSource="{Binding Items}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17" Width="432" Height="78">
                        <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                        <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </controls:PanoramaItem>
 
    <!--Panorama item scrollable-->

    <controls:PanoramaItem>
        <my:ListBoxHeaderFooter Background="Red" Margin="0,0,-12,0" Header="scrollable" Footer="Footer" ItemsSource="{Binding Items}">
            <my:ListBoxHeaderFooter.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17" Width="432" Height="78">
                        <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                        <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                    </StackPanel>
                </DataTemplate>
            </my:ListBoxHeaderFooter.ItemTemplate>                
        </my:ListBoxHeaderFooter>
    </controls:PanoramaItem>
</controls:Panorama>

Finalement, très peu de changement entre les deux PanoramaItems/ListBox.

Voyons maintenant le résultat de notre travail :

On gagne en lisibilité avec un Item visible en plus par rapport à la version normale.

On pourrait allez plus loin en créant un PanoramaScrollableItem qui gère le ListBoxHeaderFooter en interne ce qui permetterait une réutilisation plus aisée.

Vous trouverez le code source de la solution ici.

One Response to Lisibilité de PanoramaItem et Header de ListBox en WP7

  1.  

    Ca tombe bien j’étais effectivement en train de me faire la réflexion que mon panorama me bouffait un max d’espace ^^

leave your comment