Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS, MAUI

La compilation XAML

En tant que développeur Xamarin, vous avez sûrement rencontré un scénario dans lequel vous avez mal saisi un Binding et ne l'avez compris que quelques heures ou jours plus tard. Heureusement  pour se protéger de cette situation il existe la compilation XAML et les Bindings compilés !

Compilation XAML

giphyUne partie de l'amélioration de ce scénario consiste à activer la compilation XAML. Elle est désactivée par défaut, ce qui signifie que la création d'un nouveau projet ne la met pas en route, à moins que vous n’utilisiez un template qui le fasse (à vérifier sur votre setup donc). Cela est dû au fait que Xamarin souhaite garantir la compatibilité descendante car la compilation peut avoir certains effets néfastes dans de rares cas (lire la doc, lien plus haut). L'ajout de la prise en charge de la compilation XAML est aussi simple que l'ajout d'une ligne pour l'activer quelque part dans votre application. La plupart des gens choisissent de décorer directement toute l’application en agissant sur App.xaml.cs.



using Xamarin.Forms.Xaml;
...
[assembly: XamlCompilation (XamlCompilationOptions.Compile)]
namespace MyProject
{
  ...
}

Mais quel est l’effet de cet attribut ?

La partie la plus importante est qu'il vérifie les éventuelles erreurs dans fichiers XAML au moment de la compilation (et non au runtime) et vous informe immédiatement de toutes celles qu’il détecte. Avez-vous tapé accidentellement SteakLayout au lieu de StackLayout? Sans la compilation XAML activée, vous seriez toujours en mesure d'exécuter votre application et elle planterait ou ne rendrait simplement pas votre interface utilisateur comme elle le devrait.

Avec la compilation XAML activée, vous verrez des erreurs dans vos fichiers XAML apparaître dans le volet Erreurs une fois votre génération terminée. Cela permet de repérer rapidement et facilement les erreurs dans votre code XAML et de les corriger avant que l’utilisateur d’en fasse les frais. De plus, la compilation XAML réduit également la taille du fichier d'assembly et le temps d'instanciation de vos fichiers XAML, des raisons essentielles pour vous inciter à le faire !

Mise en œuvre pour comprendre

Dans la partie ci-avant nous avons ajouté la compilation XAML pour nous aider à repérer les erreurs dans nos fichiers XAML, mais malheureusement cela ne s'étend pas aux liaisons (Bindings). Nous pouvons toujours y avoir des erreurs cachées et nous n'en saurions rien tant que les erreurs n'apparaitront pas au moment de l'exécution ! C'est là que les liaisons compilées vous nous aider à parfaire notre plan !

Les Bindings habituels utilisent la réflexion pour être résolues au moment de l'exécution, ce qui rend impossible la validation au moment de la compilation. Ce processus de réflexion n'est pas non plus un processus très rentable (très lent sous OS Android notamment) et ajoute des attentes et lourdeurs inutiles en fonction de la plate-forme. Étant donné que les liaisons compilées se résolvent au moment de la compilation, un développeur peut rapidement repérer les expressions de liaison incorrectes le tout en accélérant le chargement et le fonctionnement des pages de son application ! L'activation des liaisons compilées est simple:

  • Activez la compilation XAML comme indiqué dans la section précédente.
    Utilisez l' x:DataType attribut pour fournir le type de données du contexte de liaison d'un VisualElement.

L' x:DataType attribut prend un nom de type sous forme de chaîne ou vous pouvez utiliser l'extension x:Type pour fournir un type. Le contexte de liaison de l'élément auquel vous appliquez x:DataType sera supposé être le type que vous fournissez ici. On notera que vis-à-vis de MVVM il n’y a aucun problème, ce sont les ViewModels qui ne doivent pas connaître les vues, mais les Views peuvent connaître les ViewModels. De plus, l’indication du DataType n’effectue aucune liaison réelle, c’est juste une indication pour le compilateur. Il faudra tout de même lier le ViewModel à la View et ce peu importe le moyen (ce qui fait que cela ne gêne pas votre Toolkit MVVM si vous en utilisez un).

En regardant l'exemple de code ci-dessous, nous définissons le BindingContext de la page sur une instance de MainViewModel. En définissant également le, x:DataType nous obtenons automatiquement une validation de liaison au moment de la compilation sur chaque élément sous cet élément racine. Si la propriété MyProperty propriété n'existe pas sur le MainViewModel ou si nous avons mal tapé son nom, nous verrons une erreur dans notre volet d'erreur.

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:viewmodels="clr-namespace:MyProject"
    x:Class="MyProject.MainPage"
    x:DataType="{x:Type viewmodels:MainPageViewModel}">

    <ContentPage.BindingContext>
        <viewmodels:MainPageViewModel />
    </ContentPage.BindingContext>
    
    <Label Text="{Binding MyProperty}" />
    
</ContentPage>

Liaisons compilées et DataTemplate

En tant que développeur mobile, vous avez très probablement utilisé un contrôle basé sur un modèle à un moment donné. Que ce soit pour afficher des éléments dans une liste ou un carrousel sophistiqué. Comme vous le savez peut-être, ces types de contrôles qui prennent une collection comme entrée utilisent leur propre contexte de données où chaque élément est lié à un élément de la collection. L'utilisation x:DataType à un niveau supérieur de la hiérarchie des vues ne fonctionnera pas dans cette situation.

Heureusement, pour résoudre ce problème, nous pouvons appliquer x:DataType sur l'élément DataTemplate. Comme il peut être appliqué et redéfini n'importe où dans la hiérarchie des vues, cela fonctionnera exactement de la même manière que précédemment. Voici un petit exemple de code utilisant CollectionView:

<CollectionView ItemsSource="{Binding AllItems}">
  <CollectionView.ItemTemplate>
    <DataTemplate x:DataType="{x:Type ItemViewModel}">
      <Grid>
        <Label Text="{Binding Description}" />
      </Grid>
    </DataTemplate>
  </CollectionView.ItemTemplate>
</CollectionView>

Si une propriété nommée Description n'existe pas dans la classe ItemViewModel le compilateur lèvera maintenant une erreur. Comme vous pouvez le voir, l'ajout le x:DataType le cas échéant peut vraiment vous faciliter la vie en ce qui concerne la compilation des Bindings !

Pourquoi ne pas les utiliser partout?

Il existe certains scénarios dans lesquels les liaisons compilées ne fonctionneront pas. Un exemple est l'utilisation de l'attribut Source sur une liaison. Cet attribut ne peut pas être résolu au moment de la compilation, les liaisons avec l'attribut Source sont donc exclues en tant que liaisons compilées par conception. Néanmoins, il est recommand�� de définir l'attribut x:DataType au même niveau dans la hiérarchie des vues que celui du BindingContext défini.

Conclusion

la compilation XAML est indispensable surtout sous Android où l’exécution du code de réflexion est particulièrement pénalisante. Mais les avantages concernent toutes les plateformes, notamment dans le dépistage précoce des erreurs dans les balises XAML. Mieux vaut les arrêter en développement plutôt que cela soit le client qui en fasse les frais… ou votre service de test qui remonte à vos supérieurs les bugs que vous avez laissé…

Bref, c’est mieux pour tout le monde, et vous en premier. Alors pensez-y désormais !


Stay Tuned !

blog comments powered by Disqus