Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Les Triggers XAML : Xamarin.Forms vs WPF

En complément à la série d’articles Dot.Blog et Dot.Vlog sur les Behaviors et les Triggers un petit point de comparaisons avec le père de tous les XAML n’est pas sans intérêt et répond à une question importante…

Pourquoi WPF ?

D’abord par que le XAML de WPF est le seul “vrai” XAML, le premier, le plus complet de tous, le plus abouti, c’est La référence en matière de XAML. Il est toujours bon de s’y référer pour faire des comparaisons ou tester une mouture spécifique de ce langage.

Ensuite parce que beaucoup de développeurs ont refusé UWP, le Store Microsoft et tout ce que cela suppose, Microsoft ayant mis des années avant même de penser à ajouter des possibilités de diffusion des Apps en interne dans les entreprises ce qui a terriblement pénalisé UWP. UWP C’est Windows 8 aussi, un souvenir qu’on ne peut qualifier de “bon” pour personne, utilisateurs, développeurs et Microsoft compris.

Il est donc encore très fréquent que les nouveaux projets “PC” soient écrits en Windows Forms qui est une vieillerie abominable (le pourcentage donné par MS il y a encore deux ans était effrayant, une majorité de projets !). Heureusement il y a des développeurs soucieux de concevoir des Apps modernes mais sans lien avec le Store, ceux-là choisissent naturellement WPF. La double compétence Xamarin.Forms / WPF n’étant pas rare, et le support bientôt officiel de WPF dans les Xamarin.Forms ne fera que renforcer l’attrait pour cet ancêtre qui avait en réalité 20 ans d’avance…

Je pourrais lister des tas d’autres raisons de parler de WPF, mais peu importe ce qui compte c’est que WPF est toujours d’actualité et qu’il est la référence XAML absolue.

Suite de la série Blog/Vlog sur les triggers/Behaviors en Xamarin.Forms

Dot.Vlog N°2 sur les Behaviors a été le fameux fil de la fameuse pelote de laine ! J’ai tiré un peu sur le fil et c’est toute la bobine qui est venue… J’ai ainsi continué par un article Dot.Blog précisant la différence entre les Triggers et les Behaviors. Puis saisi d’une mauvaise conscience je me suis fendu d’un nouveau Dot.Vlog, le N°5, dédié aux Triggers

Je conseille donc au lecteur de reprendre cette série pour suivre le cheminement de cette présentation multimédia multi-volets…

Quelle est la question ?

Dans le Vlog N°5 je présente une solution utilisant des Triggers pour switcher l’affichage d’un Login et d’un DisplayName selon l’existence ou l’absence de ce dernier dans la fiche de l’utilisateur fictif utilisé pour la démonstration.

La solution proposée utilise deux Labels, exactement comme la “mauvaise solution” présentée au départ pour justifier le passage aux Triggers.

Certes les Triggers vont permettre de rendre l’ensemble du code de la démonstration bien plus pro : un meilleur ViewModel sans propriétés ad hoc inutiles, un code XAML plus technique, utilisation d’un convertisseur de valeur, etc, des choses qui sont autant de prétextes de montrer du XAML sous Xamarin.Forms mais qui rendent la justification des Triggers un peu moins évidente il faut l’avouer.

Car voilà, il reste deux Labels dans le code “propre”.

D’ailleurs cela fut noté assez rapidement par un “lecteur” (regardeur ?) de ce Vlog…

Dans les coulisses du tournage du Vlog N°5 …

Selon le Vlog que je tourne je peux faire tout en une seule passe ou segmenter mes prises de vues. C’est pour cela qu’on peut me voir en éclairage nocturne ou baigné de lumière du jour sur les différentes séquences, ou l’un ou l’autre ou les deux. Pour avoir une lumière constante il me faudrait un studio toujours éclairé artificiellement de la même façon et je ne dispose pas d’un plateau télé pour tourner Dot.Vlog, n’exagérons rien Smile

Etant un minimum à l’aise avec C# et XAML, il arrive donc le plus souvent que je me lance directement. Ce fut le cas pour le Vlog N°5. J’avais bien entendu l’intention de remplacer les deux Labels par un SEUL !

Pour s’en convaincre et si vous êtes attentifs vous noterez que dans la toute première partie de la vidéo j’insiste sur les deux Labels, comme une façon de dire “vous allez voir ce que vous allez voir, ces deux là sont de trop on peut n’en avoir qu’un seul !”. J’ai eu l’intelligence de ne pas le dire (sinon j’aurais du retourner les séquences) mais j’avais insisté un peu lourdement… Si j’avais su à ce moment que cela ne serait pas possible j’aurai au contraire minimisé la présence des deux Labels sans trop revenir dessus… Il faut savoir “vendre” ce qu’on montre et aucune démo n’est totalement honnête… D’ailleurs le philosophe nous dit que toute communication est une manipulation. C’est vrai même quand on parle de la pluie et du beau temps à la machine à café… A vrai dire il faut nuancer un peu et les sociologues eux nous disent que toute communication est une influence. Ce qui revient au même sauf que dans un cas il y a intention de manipuler et pas dans l’autre.

Bref, lorsque je dis que je vais passer à la “bonne” solution et qu’on va se retrouver dans un instant “le temps que je change tout çà”. C’est vrai. Ce fut assez rapide, sauf qu’au moment de remplacer les deux Labels par un seul et donc de swticher le Binding dans le trigger (pour qu’il pointe soit sur le Login soit le DisplayName) les choses ne sont pas allées comme je le voulais…

En réalité ça plantait et j’ai passé plusieurs heures en debug pour tenter de comprendre… C’est pourquoi sur la suite il fait jour, je ne suis pas coiffé pareil, je suis en chemise et plus en t-shirt etc… ce n’est pas raccord dirait-on dans le cinéma…

Et entre temps la “bonne” solution présentée ne parle plus beaucoup des deux Labels dont la présence semble même tout à fait normale, voire obligatoire… Genre on a deux informations, il faut bien deux Labels…

Fausse logique manipulatoire…

Ruse de sioux qui bien entendu n’a pas échappée à tout le monde !

Mais ce n’est pas l’esprit de Dot.Blog, je vous devais la vérité ! Smile

Pourquoi me suis-je fait avoir ?

Deux raisons à cela :

  1. Tout simplement parce que cela fonctionne en WPF et que WPF est ma seule référence XAML consciente et inconsciente !
  2. Xamarin.Forms a un bogue dans son moteur XAML…

En quoi tout cela est-il intéressant ?

D’abord c’est important de savoir que Xamarin.Forms peut se comporter différemment de WPF ou de UWP (je n’ai pas testé sous UWP si quelqu’un veut le faire…).

Ensuite cela s’apparente à un bogue mais j’entends très bien la réponse possible qu’il s’agit d’une “feature” …

Et puis au final c’est intéressant de rappeler qu’à chaque fois qu’on passe d’une mouture à l’autre de XAML il faut absolument se forcer à se remettre dans le bon contexte car tous ces XAML ne sont pas identiques… Vouloir faire du XAML WPF avec Xamarin.Forms ne marchera pas dans tous les cas, nous en avons la preuve ici, autant qu’utiliser la syntaxe Xamarin.Forms en WPF risque de vous poser des problèmes… Et cela nous allons en avoir une illustration immédiatement !

Comment atteindre le but avec XAML WPF ?

La première chose à savoir c’est qu’en WPF les Triggers ne s’utilisent pas comme ça à la volée comme en Xamarin.Forms ! C’est un avantage de ces dernières il faut le dire, dommage que cela soit un poil bogué sur les Bindings donc.

Sous WPF les Triggers ne sont utilisables qu’à l’intérieur des Styles et des Templates. Pas dans le flux d’un code comme celui de l’exemple montré dans le Vlog N°5.

Pour adapter le code montré il faudra donc créer un Style. Heureusement pour la simplicité de l’exemple on peut déclarer ce style directement dans le contrôle, on n’est pas obligé de le créer à part dans un dictionnaire de ressources (mais c’est cette dernière façon de faire qui est la bonne).

Donc, j’ai refait entièrement le projet à l’identique sous WPF en changeant tout ce qui doit l’être (pas mal de petites choses même si globalement 90% du code est identique). Je vous ferai grâce du projet dans sa totalité puisque c’est la même chose qu’en Xamarin.Forms, sauf la déclaration de l’unique Label qui switche entre les Bindings. Et ce code est le suivant :

image

(cliquez sur l’image pour l’avoir en 100% si jamais elle est trop petite)

Il n’y a plus qu’un seul Label, enfin un TextBlock, par défaut il est formaté pour le DisplayName (FontSize à 30 et couleur à DodgerBlue).

On voit clairement en revanche que le Trigger a été enchâssé dans un Style.

On note aussi que le Binding par défaut est défini dans le Style (Binding vers DisplayName) et non pas dans la balise du contrôle TextBlock car dans ce cas il y aurait écrasement de la dernière valeur et le Trigger n’aurait pas d’effet (subtilité du moteur de valeurs de XAML).

Sinon le code est celui auquel on s’attend, si le DisplayName est vide, le Trigger se déclenche et il change le Binding pour pointer vers le Login, et il en profite pour modifier les propriétés visuelles pour recrée exactement le comportement de la démo Xamarin.Forms ! Les Triggers s’annulant grâce au fameux moteur de valeurs de XAML, lorsque la condition n’est plus vraie, toutes les propriétés de dépendances modifiées reprennent leur valeur précédente (donc couleur, taille de fonte et binding du texte). Mais cela est expliqué dans le tome 7 de AllDotBlog dédié à XAML.

Conclusion

Rien ne sert d’aller plus loin, mais il était important de répondre à la question du “pourquoi deux Labels” dans la “bonne” solution présentée dans el Vlog  N°5. Et puis parler de temps en temps de WPF, alors même que cette cible est en train d’être ajoutée aux Xamarin.Forms n’est peut-être pas totalement fortuit… Toute communication est une manipulation non ? Smile

Stay Tuned !

blog comments powered by Disqus