3

Windows 8 – Appliquer un template en fonction des items d’une liste

J’ai commencé à travailler sur Windows 8 autour d’une application utilisant des List/Grid/Gridview, en C#/XAML, et pour lesquelles je souhaitais personnaliser l’affichage de certains éléments identifiable. Par exemple, appliquer un style différent au dernier élément de la liste…

Pour l’exemple, nous allons créer une nouvelle application Windows Metro style de type Grid App (XAML) que j’ai nommé ici TemplateSelector :

clip_image001

Si on exécute l’application, voilà ce que l’on obtient :

clip_image002

Nous avons donc ici une liste d’éléments basés sur la Datasource exemple fournit par le template de projet. On voit ici que chaque élément utilise le même template : Standard250x250ItemTemplate.

<DataTemplate x:Key="Standard250x250ItemTemplate">
        <Grid HorizontalAlignment="Left" Width="250" Height="250">
            <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                <Image Source="{Binding Image}" Stretch="UniformToFill"/>
            </Border>
            <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
                <TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
            </StackPanel>
        </Grid>
    </DataTemplate>

Imaginons que l’on souhaite que l’élément 3 de notre premier groupe possède un cadre bleu, c’est à dire, appliquer un style différent que Standard250x250ItemTemplate utilisé.

Pour cela il existe une classe DataTemplateSelector : http://msdn.microsoft.com/fr-fr/library/system.windows.controls.datatemplateselector.aspx

Pour l’implémenter c’est simple, il suffit de créer une classe qui hérite de DataTemplateSelector et de surcharger la méthode SelectTemplateCore.

Ajoutons une classe à notre projet, que j’ai nommé ici MyTemplateSelector :

clip_image003

Voici le code de ma classe MyTemplateSelector :

public class MyTemplateSelector : DataTemplateSelector
    {
        protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore
            (object item, Windows.UI.Xaml.DependencyObject container)
        {
            if (item is SampleDataItem)
            {
                SampleDataItem sample = item as SampleDataItem;
                if (sample.UniqueId == "Group-1-Item-3")
                    return Application.Current.Resources["Special250x250ItemTemplate"] as DataTemplate;
                else
                    return Application.Current.Resources["Standard250x250ItemTemplate"] as DataTemplate;
            }
            return base.SelectTemplateCore(item, container);
        }
    }

Ici, en fonction de l’Identifiant de l’item en cours, j’applique soit le template Standard250x250ItemTemplate, soit le template Special250x250ItemTemplate dans le cas ou l’Identifiant est "Group-1-Item-3" dans mon exemple et en me basant sur la Datasource du template de projet.

Il faut penser à créer le template Special250x250ItemTemplate, dans le fichier StandardStyles.xaml par exemple :

<DataTemplate x:Key="Special250x250ItemTemplate">
        <Grid HorizontalAlignment="Left" Width="250" Height="250">
            <Border BorderBrush="Blue" BorderThickness="12" Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                <Image Source="{Binding Image}" Stretch="UniformToFill"/>
            </Border>
            <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
                <TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
            </StackPanel>
        </Grid>
    </DataTemplate>

Il ne reste plus qu’à dire à notre GridView d’utiliser notre classe MyTemplateSelector. Pour cela, il suffit d’ajouter, dans le code XAML de la page, la ressource :

<common:MyTemplateSelector x:Key="TemplateSelector" />

Puis au niveau du GridView de spécifier la propriété ItemTemplateSelector :

<GridView
            x:Name="itemGridView"
            AutomationProperties.AutomationId="ItemGridView"
            AutomationProperties.Name="Grouped Items"
            Grid.Row="1"
            Margin="0,-3,0,0"
            Padding="116,0,40,46"
            ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
            ItemTemplateSelector="{StaticResource ResourceKey=TemplateSelector}"
            SelectionMode="None"
            IsItemClickEnabled="True"
            ItemClick="ItemView_ItemClick"> 

Attention, il faut également supprimer la propriété ItemTemplate du GridView sinon, il ne passera pas par notre classe MyTemplateSelector.

Remarque, on peut aussi appliquer ces valeurs au niveau du code behind C# :

this.itemGridView.ItemTemplate = null; 
this.itemGridView.ItemTemplateSelector = new MyTemplateSelector(); 

Si on exécute désormais notre application, voici ce que l’on obtient :

clip_image004

Nous savons désormais comment personnaliser nos éléments dans une liste. Les possibilités sont assez nombreuses. Dans mon cas, j’ai utilisé ce principe pour ajouter un élément en fin de ma liste qui me permet de faire de la pagination.

Par défaut ma liste charge 40 éléments, le dernier élément est un + qui lorsque l’on clique dessus, charge les 40 éléments suivants :

clip_image005

Rock’n’Roll.

gbrout

Architecte, formateur MCT et expert sur la gamme Visual Studio ALM qu'il met en œuvre sur l'ensemble des projets. Il travaille pour la société Itelios, spécialisée dans les technologies Microsoft et le commerce connecté. Il accompagne quotidiennement de nombreuses équipes et projets dans différents domaines et technologies : Windows 8, Windows Phone, ASP.NET MVC, Dynamics CRM... Passionné par le développement, ses domaines de prédilections sont avant tout l'expertise technique, l'industrialisation des développements avec la gamme Visual Studio ALM, l'analyse des performances, les tests et tout ce qui a trait à la qualité. Son expertise sur les  technologies Microsoft sa passion pour les nouvelles technologies et les développements novateurs l'a conduit à l'écriture d'un livre accessible et opérationnel sur le développement pour Windows 8 à l'aide d'HTML5 et JavaScript. Il anime également des conférences et sessions techniques telles que des live meeting en ligne ou lors d’événements comme les Techdays.

3 Commentaires

  1. Article sympa mais j’ai une question:
    Est-ce que le rendu final est fait par un moteur WEB ou autre? Suggères-tu utiliser XAML au lieu de HTML/CSS/JavaScript pour le développement d’application Windows 8 style metro, et si oui, pourquoi?

  2. Salut Ilyas,

    En réalité Microsoft à mis en place un nouveau runtime WinRT : WinRT

    Le Windows RunTime associe le code fonctionnel de celui réservé à l’affichage et la présentation. Par exemple, un développeur peut utiliser le C# puis l’associer au XAML. De même, il peut se tourner vers le JavaScript associé aux HTML5 et CSS. Derrière WinRT utilise soit l’interpreteur XAML, soit le moteur de rendu IE10.

    Je n’est pas réellement de préférence quand au choix C#/XAML ou HTML5/JS. Je ne me suis pas encore penché assez sur HTML5/JS pour avoir des points de comparaisons, notamment est-ce que l’un est plus performant que l’autre… Je dirai que ça dépend avant tout de ton background en développement. Microsoft à surtout, selon moi, mis à disposition HTML5/JS pour attirer plus de monde et surtout les développeurs WEB à développer des applications pour Windows 8.

    A+

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *