[POC] Grid vNext

J’aime bien les contrôles de positionnement dans XAML et je suis particulièrement fan du contrôle Grid.
Pour rappel, celui ci se comporte comme un tableau que l’on définit via ses propriétés RowDefinitions et ColumnDefinitions.
Les enfants du Grid sont positionnables individuellement en affectant les propriétés Grid.Row et Grid.Column.

Voici un Grid classique dont les deux enfants, un bouton et une checkbox, sont positionnés via Grid.Row et Grid.Column.

<Grid>

    <!-- Déclaration de 3 lignes --> 
    <Grid.RowDefinitions>
        <!-- Place du Titre -->
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <!-- Déclaration de 3 colonnes -->
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Button Content="Title" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch"></Button>
    <CheckBox Content="Footer" Grid.Row="2" Grid.Column="2" ></CheckBox>
</Grid>

Simple non ?
Pourtant lorsque l’on se sert régulièrement du panel Grid, on s’aperçoit que cette façon de placer les éléments est aussi une faiblesse.
La faute à son positionnement par index !

Pour s’en convaincre il suffit d’ajouter un RowDefinition de plus à notre déclaration (ici pour donner de la place à un élément SystTray):

    <!-- Déclaration de 3+1 lignes --> 
    <Grid.RowDefinitions>
        
        <!-- Place de la Systray -->
        <RowDefinition Height="32"/>
        <!-- Place du Titre -->
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

Que va t’il se passer ?

Le bouton a la propriété Grid.Row affecté 0 et va donc prendre la place allouée normalement à l’élément Systray
La CheckBox de la même manière remonte d’une ligne.

Les éléments étant positionnés par des index ils ne sont pas relatif à l’emplacement auquel ils ont été initialement affectés.
Pour nos deux éléments ce n’est pas très grave, il suffit d’incrémenter les Grid.Row et chacun retrouve sa place mais imaginez maintenant que ce problème s’applique sur une interface complexe comportant des dizaines d’éléments. Cela peut rapidement devenir un cauchemar à gérer.

Positions relatives

Pour ne plus être sous le coup de l’indexation, il suffirait d’adresser les RowDefinitions non plus par index mais par nom.
Ainsi même si une ligne est rajouté, l’index bougera mais pas le nom.

Comme la fonctionnalité n’existe pas en XAML, j’ai crée un petit Behavior permettant la prise en compte des noms.

DISCLAIMER: Ce Behavior un POC et ne devrait pas, normalement, être utilisé en production (même si le résultat fonctionne plutôt bien 😛 )

Son fonctionnement est très simple : lorsque la propriété sb:GridEx.RowName est affectée dans le Button et la CheckBox, il va inspecter la liste des RowDefinitions de la Grid et voir si une des lignes possède le même nom. Si c’est le cas il récupère son index et l’affecte à ses enfants (Grid.Row=’0′).

<Grid>

    <Grid.RowDefinitions>
        <RowDefinition x:Name="Title"/>
        <RowDefinition x:Name="Body"/>
        <RowDefinition x:Name="Footer"/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="Left"/>
        <ColumnDefinition x:Name="Center"/>
            <ColumnDefinition x:Name="Right"/>
    </Grid.ColumnDefinitions>

    <Button Content="Title" sb:GridEx.RowName="Title" sb:GridEx.ColumnName="Center" HorizontalAlignment="Stretch"></Button>
    <CheckBox Content="Footer" sb:GridEx.RowName="Footer" sb:GridEx.ColumnName="Right" ></CheckBox>

</Grid>

En plus de ne plus être assujetti à l’indexation, les placements des éléments sont beaucoup plus clairs.
Par exemple Le bouton est positionné dans la colonne « Center » et la ligne « Title ».
C’est beaucoup plus parlant que la colonne 1 et ligne 0 !

Conclusion

L’idée de ce POC était de mettre en avant une des faiblesses du panel Grid : Son positionnement par index.
Une vNext de ce panel pourrait intégrer un positionnement relatif par nom.
D’ailleurs lorsque l’on regarde le tout nouveau RelativePanel de Windows 10, on constate qu’il se positionne relativement aux noms des contrôles de la page.

Vous trouverez le code source du behavior.

leave your comment