Dot.Blog

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

Utiliser des Behaviors dans des applications Windows 8 Store

[new:31/12/2012]Les Behaviors ne sont pas récents, ils existent depuis Silverlight 3, et leur succès n’a d’égal que leur valeur : notamment sous MVVM (mais pas seulement) ils permettent souvent de gérer de nombreuses situations de façon élégantes côté Xaml. Hélas .NET sous WinRT ne gère pas les Behaviors. Mais il existe une solution…

Les Behaviors

En bon français nous parlerions de “comportements”. En effet quand on ajoute un Behavior à un contrôle il s’agit bien de lui ajouter un “comportement” particulier.

Les Behaviors ont été introduits, comme de nombreuses autres bonnes idées de Xaml, d’abord dans Silverlight. La version 3 pour être précis. Et bien entendu dans Expression Blend, l’outil de développement le plus excitant et le mieux fait que je n’ai jamais vu. Je sais que nombreux sont les développeurs à “ne rien comprendre” à Blend, c’est pourquoi j’insiste. Blend est juste fantastique et reste le seul outil sérieux pour travailler en Xaml dès qu’on dépasse l’alignement de deux TextBox dans une Grid…

Mais revenons aux Behaviors. Après cette première percée dans Silverlight 3, et comme une si bonne idée ne pouvait rester qu’une simple curiosité d’un seul des “enfants” de Xaml, on a vite retrouvé leur implémentation dans les versions de Xaml pour Windows Phone 7 et même WPF (tout comme le Visual State Manager).

Des propriétés … attachantes

Techniquement les Behaviors ne sont rien d’autre qu’une implémentation particulière des Propriétés Attachées. Ces dernières permettent de définir des propriétés au niveau d’un contrôle parent qui se propagent vers les contrôles enfants. C’est par exemple le cas de Top et Left qui sont des propriétés de Canvas mais qui sont manipulables dans tout contrôle qu’on pose sur un Canvas pour en fixer la position. La propriété est bien définie au niveau de Canvas, et c’est elle qui gère les différentes valeurs données à chaque contrôle enfant. Mais côté développeur, c’est bien dans chaque enfant qu’on saisit le Top et le Left… Idée brillante s’il en est, comme beaucoup d’autres dans Xaml comme le Binding qu’aucun ersatz actuel n’a pu égaler (qu’il s’agisse de HTML 5, de Android ou iOS pour ne parler que des principaux environnements concurrents).

D’autres exemples simples de propriétés attachées viennent immédiatement à l’esprit : Row et Column pour les enfants d’une Grid notamment. Le principe est simple, l’implémentation aisée, il est dommage de constater que les développeurs ne s’en servent pas plus souvent dans leurs propres contrôles (ceux qui produisent des contrôles sont d’ailleurs assez rares eux-mêmes !).

Des propriétés auxquelles ont devient… dépendant

Tout cela n’est au final qu’une variante spécialisée des Propriétés de Dépendances.

Si vous ne connaissez pas bien ces propriétés particulières je vous conseille mon billet “Les propriétés de dépendances et les propriétés jointes sous WPF” accompagné d’un article PDF de 25 pages accompagné d’un projet exemple (vous noterez l’hésitation de traduction entre “jointes” et “attachées”, l’article date de 2009 et la communauté française n’était pas encore très fixée sur ce point de langage…).

Comme je le disais, les Behaviors ne sont que des propriétés attachées. Dans un Behavior les valeurs des propriétés attachées sont utilisées pour configurer un ou plusieurs gestionnaires d’évènement. Un Behavior c’est à la fois un trigger (un évènement – ou plusieurs – dont le déclenchement est écouté) et une ou plusieurs actions paramétrables exécutées lorsque le ou les triggers se déclenchent.

Les Behaviors : de l’action sans code

L’intérêt des Behaviors est de pouvoir encapsuler les conditions d’un déclenchement et les actions qui doivent en découler sous la forme d’un composant réutilisable qu’on peut déposer sur n’importe quel contrôle (sauf si des limitations propres au Behavior considéré s’appliquent). L’un des gros avantages des Behaviors est d’apparaitre sous la forme de composants “visuels” se plaçant dans l’arbre graphique d’un code Xaml. Les Triggers de WPF peuvent sembler assez similaires dans leur description mais ils sont très différents dans ce qu’on peut en faire, il ne faut donc pas confondre ces deux façons d’ajouter des actions à un contrôle.

On notera qu’un Behavior est techniquement une classe générique, ce qui permet aisément de fixer en paramètre le nom de la classe cible. Celle-ci peut être très précise - Behavior<TextBlock>ne fonctionnera que sur des TextBlock – ou bien plus générale (en utilisant un ancêtre de toute une branche de Xaml). Cette souplesse offre la possibilité de pouvoir personnaliser à l’extrême un Behavior qui ne peut être utilisé qu’avec une classe précise ou bien de créer des comportements plus généraux (par exemple qui ne vont que changer la Visibilty, présente dans tout contrôle).

Il est donc possible d’ajouter des comportements, éventuellement complexes, qui se posent sur un contrôle visuel avec la même simplicité qu’on placerait un effet visuel de flou par exemple (les pixel shaders). C’est une avancée énorme permettant à des développeurs de fournir aux designers tout ce qu’il faut pour travailler sans que ces derniers n’aient à savoir coder. On retrouve ici tout l’esprit de la séparation code / UI qui se prolonge dans l’application d’un pattern comme MVVM.

Le lecteur intéressé trouvera ici un billet et son code exemple sur les pixel sharders.

Dot.Blog a déjà parlé de presque tout en près de 600 billets depuis sa création, n’hésitez pas à utiliser la fonction de recherche en haut de l’écran !

Les exemples de Behaviors ne manquent pas, j’ai publié il y a déjà un moment toute un librairie qui en regroupe des dizaines (My Behavior Collection). Par exemple on peut supposer un Behavior qui, lorsqu’il s’attache à un TextBox lui confère le comportement “sélectionner tout le texte sur la prise de focus”, rendant ainsi le changement de la valeur beaucoup plus rapide pour l’utilisateur. Et tout cela sans avoir besoin de créer un contrôle TextBox spécialisé, ni d’écrire de code-behind et sans jamais toucher le ViewModel qui est derrière la vue concernée !

Plus fort, les Behaviors peuvent être combinés. Il est donc possible d’ajouter plusieurs Behaviors à un même contrôle pour lui conférer immédiatement tout un tas de comportements différents sans jamais écrire de code (en tout cas répétitif). Une fois un Behavior écrit il est utilisable partout, même dans d’autres projets. C’est un gain de productivité important car les Behaviors amènent la réutilisation du code propre à la programmation objet au niveau du visuel sans demander des compétences de programmation à celui ou celle qui fabrique ce visuel.

Puisque les Behaviors peuvent être combinés, il est bien entendu plus intelligent de créer des behaviors simples, s’occupant d’un seul comportement, que de vouloir créer des monstres automatisant plusieurs comportements à la fois et qui seront donc plus difficiles à réutiliser ailleurs dans d’autres projets…

Bref, les Behaviors c’est extraordinaire, il faut s’en servir le plus souvent possible.

Pour aller plus loin avec les Behaviors je vous suggère ces billets :

 

La mauvaise nouvelle

Hélas, le profile .NET de WinRT ne contient pas les Behaviors… Faute de temps pour les implémenter dès la sortie de Windows 8 certainement.

On sait que Sinofsky voulait la peau de Roger Silverlight, celle de son complice C# ainsi que le cousin WPF et leur mère à tous .NET.

Tous les dictateurs et les psychopathes ont, je ne sais pas pourquoi, chacun leurs petites lubies vis à vis de tel ou tel groupe, de pogrom en épuration ethnique, tous ont en marotte un peuple à massacrer, même quand cela ne gêne en rien leur pouvoir absolu. Chez Sinofsky c’était .NET, C# et Xaml. Allez comprendre…

En prenant en compte cet élément essentiel à la compréhension des choses on peut imaginer que l’équipe Xaml n’a pas du se voir réserver les meilleures conditions de travail ni le plus gros budget…

Des âneries comme Html5/WinJS ou le retour de l’ancêtre barbu champion des memory leaks C++ était plus son truc à Sinofksy. Un vrai ringard dont le départ précipité de chez Microsoft aurait été encore plus grand s’il avait eu lieu encore plus tôt.

Mais comme dans les contes de Noël l’histoire se finit bien et le méchant est puni.

La tradition chère à cette période si particulière de l’année est donc sauve et nous sommes débarrassés de l’odieux tyran qui a fait commettre à Microsoft beaucoup d’erreurs dont la mise à l’écart de C# / Xaml n’est peut-être pas la plus grave d’ailleurs.

Il reste qu’il n’y a pas de support des Behaviors dans le Xaml du profile .NET sous WinRT et personne ne peut prédire ce que sera l’action ni l’influence de Julie Larson-Green, même si nous appelons d’ores et déjà de nos vœux un changement en profondeur dans les méthodes de travail que nous espérons tous plus harmonieuses et dénuées de la haine sinofskienne irrationnelle à l‘égard de C#, Xaml, WPF et Silverlight.

La Hollande à notre secours

Non, je ne parle pas de la compagne de notre Président. D’ailleurs il serait difficile de l’appeler ainsi puisqu’elle ne porte pas le même patronyme, et même dans ce cas un gentleman ne saurait l’apostropher de la sorte. Même si elle semble avoir des dons certains pour buzzer sur Twitter je ne pense pas qu’elle soit assez geek pour nous sortir de l’affaire de toute façon…

Je ne parle pas non plus de “l’autre pays du fromage”, avec un seul de connu cela fait maigre pour se comparer à notre patrie fière de ses centaines de merveilles dures ou coulantes, pures ou marbrées, voire veinées de moisissures amicales, aux senteurs variées comme un champ de blé ou un automne pluvieux et aux saveurs milles fois renouvelées que la planète entière nous envie (ou pas, mais ça c’est la jalousie certainement).

Je veux juste parler du pays de Joost van Schaik.

Un hollandais. De Hollande donc.

Ce gentil développeur a en effet eu l’idée de partir des propriétés attachées pour recréer le code des Behaviors, les rendant ainsi disponibles dans Xaml sous WinRT.

C’est par ce poste que les choses ont commencé : http://dotnetbyexample.blogspot.be/2012/03/attached-behaviors-for-windows-8-metro.html

Toutefois les choses se sont ensuite un peu plus structurées et cette idée est devenue un projet CodePlex, les WinRtBehaviors.

Des Behaviors en construction

Certes, cette implémentation n’est pas tout à fait identique aux Behaviors originaux. Mais au fil du temps et des efforts le code original a évolué. Les propriétés de ces nouveaux Behaviors peuvent ainsi être bindées, comme les “vraies”, de même une tentative de blendability a permis de pouvoir ajouter visuellement les Behaviors sans avoir à tout taper par code.

Finalement ça avance plutôt bien et il existe même un package Nuget qu’on peut facilement installer dans ses applications.

Même si ces Behaviors ne sont pas encore parfaits, ils permettent de faire revenir cette fonction que certains jugent essentielles dans Xaml (ce que j’agréée).

Des exemples

Les Behaviors qu’on peut écrire sont identiques aux originaux puisqu’on doit dériver son code de la classe générique Behavior<> et qu’ensuite il faut overrider OnAttached() et OnDetaching() et ajouter les propriétés nécessaire au fonctionnement du nouveau Behavior.

Je renvoie ainsi le lecteur à la collection de Behaviors que j’ai publiée (avec source) citée plus haut dans ce billet. C’est une bonne base qui permet de voir l’implémentation de différents behaviors.

Vous trouverez aussi un article assez complet sur ces Behaviors pour WinRT (en anglais) avec un exemple d’implémentation et surtout d’utilisation en Xaml ici : http://blogs.u2u.be/diederik/post/2012/10/28/Using-Behaviors-in-Windows-8-Store-Apps.aspx

Conclusion

Les Behaviors sont des outils très importants sous Xaml, souvent méconnus ou peu utilisés, leur absence sous WinRT n’aide pas à les faire mieux connaitre…

Ce billet, et le code CodePlex ici présenté auront, je l’espère, donné envie aux lecteurs de regarder de plus près cette possibilité offerte en Xaml, et pas seulement sous WinRT puisque les Behaviors existent sous leur forme parfaite (et supportée visuellement par Blend) sous Silverlight et WPF.

Bon développement,

Et Stay Tuned !

blog comments powered by Disqus