Loupe

#Windows 10 Le RelativePanel, un nouveau contrôle XAML

Windows 10 vient avec de nombreuses fonctionnalités en termes de développement. Parmi celles-ci, un nouveau contrôle XAML fait son apparition : le RelativePanel.

 

Introduction au RelativePanel

image

 

Cela fait maintenant un moment que nous sommes habitués à utiliser des Grids, des StackPanels et tous les autres contrôles XAML. Il arrive assez souvent que le XAML devienne assez dense et on arrivait vite à s’embrouiller dans notre layout : “Attends, ça va dans la Row 3, et la Column 2, il faudrait que je le mette dans la Row 1 avec un RowSpan de 2 plutôt…...?

L’objectif du RelativePanel est de clarifier ce XAML et d’éviter les imbrications multiples. Son fonctionnement est plutôt simple : il dispose les éléments en déclarant les relations entre les enfants, et cela grâce à 16 différentes attached properties. Mais on pourra aussi agencer les enfants vis à vis du parent.

 

Alignement avec le Panel

Tout d’abord, le comportement de base est celui d’une Grid. Le contrôle va se placer en haut à gauche du RelativePanel.

<RelativePanel Padding="24">
        <Rectangle x:Name="Rect1" Width="100" Height="100" Fill="Crimson"/>
</RelativePanel>

clip_image001

 

Ensuite, on va aligner notre rectangle au centre du Panel. Là ou on aurait fait HorizontalAlignment=”Center” et VerticalAlignment=”Center” dans une Grid, nous avons :

<RelativePanel Padding="24">
        <Rectangle x:Name="Rect1" Width="100" Height="100" Fill="Crimson"
                   RelativePanel.AlignHorizontalCenterWithPanel="True"
                   RelativePanel.AlignVerticalCenterWithPanel="True" />
</RelativePanel>

clip_image002[6]

 

Ainsi, pour aligner ses contrôles par rapport au RelativePanel, 6 attached properties sont mises à disposition :

<Rectangle x:Name="Rect1" Width="100" Height="100" Fill="Crimson"
           RelativePanel.AlignVerticalCenterWithPanel="True"
           RelativePanel.AlignHorizontalCenterWithPanel="True"
           RelativePanel.AlignRightWithPanel="True"
           RelativePanel.AlignLeftWithPanel="True"
           RelativePanel.AlignTopWithPanel="True"
           RelativePanel.AlignBottomWithPanel="True"/>
Avec AlignTopWithPanel=”True”, on aligne le Top de l’élément avec le Top du Panel, et ainsi de suite pour chaque propriété.

Ainsi, vous l’aurez compris : les valeurs par défaut sont AlignLeftWithPanel=”True” et AlignTopWithPanel=”True”. Et il est intéressant de savoir que le fait de spécifier à la fois AlignLeftWithPanel=”True” et AlignRightWithPanel=”True”  va centrer le rectangle dans le Panel.

 

Alignement avec les autres éléments

C’est ici tout l’intérêt du RelativePanel. Tout d’abord, on retrouve les mêmes attached properties comme pour le Panel, mais à la place d’un booléen on doit spécifier le nom de l’élément avec lequel on veut interagir. On utilise donc des attached properties telle que AlignVerticalCenterWith=”MonUserControl”.

<RelativePanel Padding="24">
        <Rectangle x:Name="Rect1" Width="100" Height="200" Fill="Crimson"
                   RelativePanel.AlignHorizontalCenterWithPanel="True"
                   RelativePanel.AlignVerticalCenterWithPanel="True"/>

        <Rectangle x:Name="Rect2" Width="100" Height="100" Fill="CadetBlue"
                   RelativePanel.AlignVerticalCenterWith="Rect1"/>
</RelativePanel>

clip_image002[10]

 

Ici, on demande au rectangle bleu de s’aligner verticalement avec le rectangle rouge, mais on pourrait très bien lui demander d’aligner son Top avec le Top du rectangle rouge, en remplaçant le RelativePanel.AlignVerticalCenterWith par AlignTopWith, on obtient :

<Rectangle x:Name="Rect2" Width="100" Height="100" Fill="CadetBlue"
           RelativePanel.AlignTopWith="Rect1"/>

clip_image002[12]

 

On a donc toute cette panoplie pour notre layout :

<Rectangle x:Name="Rect2" Width="100" Height="100" Fill="CadetBlue"
           RelativePanel.AlignHorizontalCenterWith="Rect1"
           RelativePanel.AlignVerticalCenterWith="Rect1"
           RelativePanel.AlignLeftWith="Rect1"
           RelativePanel.AlignRightWith="Rect1"
           RelativePanel.AlignTopWith="Rect1"
           RelativePanel.AlignBottomWith="Rect1"/>

En réalité, ce n’est pas tout, il y a aussi…

 

Above, Below, LeftOf, RightOf

Je pense que les noms sont assez explicites et vous propose tout simplement un exemple :

<Rectangle x:Name="Rect2" Width="100" Height="100" Fill="CadetBlue"
           RelativePanel.LeftOf="Rect1"
           RelativePanel.Above="Rect1"/>

clip_image002[14]

 

Le rectangle bleu va venir se placer au dessus du rectangle rouge avec “Above” et à sa gauche avec “LeftOf”. On peut voir ça de la sorte : Aligner le Right du rectangle bleu avec le Left du rectangle rouge ainsi que le Bottom du rectangle bleu avec le Top du rectangle rouge.

On peut donc jouer avec les propriétés suivantes :

<Rectangle x:Name="Rect2" Width="100" Height="100" Fill="CadetBlue"
           RelativePanel.LeftOf="Rect1"
           RelativePanel.RightOf="Rect1"
           RelativePanel.Above="Rect1"
           RelativePanel.Below="Rect1"/>

Conclusion

Je pense que le RelativePanel est un contrôle très intéressant et qu’il va être très utiles pour certains comportement. Il va nous éviter de nombreux Grid/StackPanel imbriqués et, de ce fait, nous apporter une certaine clarté dans le XAML pour des layouts simples mais auxquels nous avons affaire fréquemment.

Cependant, c’est une manière de voir la composition du layout un peu différente de nos habitudes et il faudra peut être un petit temps d’adaptation pour l’utiliser dans des cas un peu plus “touchy”.

Avec les AdaptiveTriggers qui viennent aussi avec Windows 10, les possibilités seront très intéressantes. La première chose qui me vient à l’esprit est la gestion des formulaires en mode responsive, on aurait :

<Grid x:Name="LayoutRoot" Background="White">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="NormalState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="800" />
                </VisualState.StateTriggers>

                <VisualState.Setters>
                    <Setter Target="TxtBox.(RelativePanel.RightOf)"
                            Value="Label"/>
                </VisualState.Setters>
            </VisualState>

            <VisualState x:Name="SpecialState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>

                <VisualState.Setters>
                    <Setter Target="TxtBox.(RelativePanel.Below)"
                            Value="Label"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroup>

    <RelativePanel Padding="24">
        <TextBlock x:Name="Label" Text="Label" />
        <TextBox x:Name="TxtBox" Background="Blue" />
    </RelativePanel>
</Grid>

image

 

On peut voir que l’implémentation d’un tel comportement est vraiment simple et rapide à développer. Je suis impatient de pouvoir utiliser tout ça dans de réels projets concrets !

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus