Dot.Blog

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

Le défi des nouvelles interfaces XAML - La cassure conceptuelle

J'ai l'habitude de publier ici du code, des tutors et des informations qui sont majoritairement très techniques. Il y a certains sujets où il me semble bon de prendre un peu de recul, les nouvelles interfaces utilisateurs le méritent largement. En effet, l'avalanche à la fois technologique et visuelle qui accompagne Silverlight et WPF, peut faire oublier l'objectif réel et le changement de paradigme, le nez collé à la vitrine, la tête dans le guidon pour ingurgiter les propriétés de dépendance ou les RIA Services on ne prend pas assez le temps de réfléchir plus globalement...

Ce billet sera donc une pause dans ce rush, on s'assoit, on prend le temps de réfléchir.

Pourquoi "nouvelles" interfaces ?

Comme vous l'avez certainement compris, quelque chose a changé. Il suffit de regarder Surface et son interface pour comprendre que ce changement n'est pas uniquement cosmétique, il est profond et touche aussi bien à la représentation des données qu'à l'interaction homme / machine. C'est pourquoi je parle ici de "nouvelles" interfaces utilisateur.

N'est-ce qu'une question de mode ?

Oui et non.

Oui car tout est mode chez l'humain... La façon de se coiffer, de s'habiller, la forme des voitures, celle des cafetières, etc. L'informatique, dans sa partie visuelle et interactive n'échappe pas à ce mouvement perpétuel. Le fait qu'un programme puisse se manipuler selon des concepts "à la mode" n'est donc pas "honteux" ni même accessoire ! C'est ainsi que l'humain vit, c'est ainsi qu'il imprime sa marque à l'environnement qui l'entoure.
L'humain est le seul animal a modifier son environnement pour le faire correspondre à ses rêves, là où tous les autres animaux subissent de plein fouet la sélection darwinienne et ce qu'on appelle la pression de l'environnement sans rien pouvoir y changer. Il y a donc bien un phénomène de mode dans ces "nouvelles interfaces" mais nous venons de voir que mode et civilisation humaine sont deux choses inséparables...

Non car on a tendance à associer les modes à la simple cosmétique et que le changement qui s'opère est bien plus conceptuel qu'un simple "relookage". J'y reviens plus loin.

Qu'est-ce qu'une mode ?

Pour ce qui nous intéresse ici, car sinon on pourrait en faire largement un sujet de thèse, disons qu'une mode est une façon collective et temporaire de faire les choses ou de les représenter.

Comment passe-t-on d'une mode à l'autre ?

Pour l'illustrer, une petite anecdote :

J'étais chez mon père il y a quelques jours et il venait de s'acheter une machine à café Senseo (lassé qu'il était de se faire racketter par les dosettes Nespresso du bellâtre "What else?"). Surprise ! ce modèle est rectangulaire alors que les Senseo, jusqu'à lors, était tout en rondeur (le nouveau modèle n'est d'ailleurs même pas encore sur leur site). Un changement de mode s'opère... Mais comment ? Ici on le voit, la mode était aux rondeurs, elles semblent passer aux formes plus carrées. Il est de même en informatique : Windows nous a habitués à ses débuts à des fenêtres bien rectangulaires aux angles bien droits. Ces fenêtres plates et rectangulaires ont fini par lasser. Windows avec XP et plus encore avec Vista et 7 est donc passé aux rondeurs. La "classe" absolue ayant été au début de cette mode de faire tourner ses applications dans une fenêtre non rectangulaire ! Allons-nous revenir à des fenêtres rectangulaires à l'instar des formes de la nouvelles Senseo ? Le nouveau paradigme qui préside à la conception des "nouvelles interfaces" se résume-t-il à cela ?

La cassure conceptuelle

De nombreuses modes en effet se sont juste résumées à cela : un changement de forme. Quand tout est rond on finit par revenir à quelque chose de plus carré et inversement. Le triangle, malgré sa très grande force symbolique ne se prête guère à l'affichage écran. Exit le triangle, le losage n'étant guère plus pratique, peut-être qu'un jour la mode sera aux fenêtres patatoïdes !

Les nouvelles interfaces homme / machine se situent-elles uniquement sur le plan esthétique ?

Encore une fois : Oui et non.

Oui car il est impossible pour une représentation d'échapper à la mode ambiante, ou celle à venir. Il en va de même en écriture par exemple.
On peut écrire des choses très nouvelles sur un sujet, mais il faudra bien se plier aux exigences de la langue de son pays, telle qu'elle est parlée au moment où l'on écrit.
On voit mal un philosophe contemporain ou même un simple romancier publier un ouvrage en latin ou en vieux français. Certains mots sont plus "à la mode" que d'autres, et s'il ne veut pas que sa prose "sente la naphtaline" il faudra qu'il emploie les mots, expressions et formes grammaticales de son temps.
Sinon il risque tout simplement de ne pas être lu/écouté, pire de ne pas être compris. Car la mode est un code culturel qui fait partie intégrante de la communication et donc de la compréhension entre l'émetteur et le récepteur d'une information. 
Il y a donc toujours une part d'allégeance à la mode en cours dans toute forme de communication. Cette mode pouvant même varier au sein d'une même société selon la cible visée (on ne s'adresse pas à la célèbre ménagère de moins de 50 ans des sondages comme à l'ado qui écrit en langage texto).
La mode, ainsi exprimée, s'intègre dans un corpus de règles sociales et morales plus large qu'on appelle les us et coutumes. Vouloir y échapper n'est pas forcément faire preuve d'originalité. Refuser la mode par simple réaction c'est aussi se couper de ses contemporains. Mais on peut aussi créer la prochaine mode...

Non car on assiste aujourd'hui à une cassure conceptuelle. Une rupture qui peut largement être minorée, voire ignorée, cachée qu'elle est, justement, derrière l'écran de fumée du simple phénomène de mode perçu comme seule modification esthétique.

Quelle est cette cassure conceptuelle ?

Elle est de taille ! Prenons un exemple concret : vous devez créer un logiciel de surveillance bancaire. Ici tout n'est que séries de chiffres, de pourcentages, de tendances à la hausse ou la baisse. Comment allez-vous créer l'interface d'un tel logiciel ?

La plupart des informaticiens se plongeront d'abord dans le code et poseront ensuite rapidement quelques grilles, ces horribles tableaux rectangulaires que tout éditeur de composants se doit d'avoir perfectionné à sa manière.

Va-t-il suffire de "templater" une DataGrid sous Blend en lui mettant des coins arrondis pour dire qu'on a utiliser correctement Silverlight ou WPF ?

Là, en revanche une seule réponse, claire et nette : Non !

Se servir du potentiel créatif de Silverlight et WPF ne consiste certainement pas à relooker les cases à cocher ni à "coller" un drop shadow à une boîte de dialogue ! Agir ainsi est un gâchis énorme, et surtout c'est ne pas avoir compris la cassure conceptuelle qu'impose ces outils.

Revenons à notre hypothétique application de surveillance. Supposons pour simplifier qu'elle permette à l'utilisateur d'avoir un oeil sur les actions de son portefeuille. La surveillance pouvant être activée ou désactivée pour chaque action.

La première tentation sera ainsi de représenter la liste des actions sous la forme d'une grille de données. On aura l'impression de profiter de toute la technologie en templetant la grille pour ajouter le logo de la société, des petites pastilles qui changent de couleur quand le logiciel teste une action, une autre quand l'action est à la hausse ou à la baisse, etc. On ira même jusqu'à ajouter quelques animations, c'est tellement "fun". L'utilisateur naviguera entre les pages qui coulisseront à l'écran de droite à gauche et réciproquement, etc. Là on aura eu l'impression de faire du neuf et d'exploiter à fond les possibilités de Silverlight/WPF !

Hélas, que nenni... En réalité ce qui aura été fait n'aura concerné que la seule apparence. Mettre du rond là où c'était habituellement carré ou l'inverse. C'est la mode dans son sens le plus négatif et le plus péjoratif qui soit : une lubie temporaire qui fait que si on n'a pas les dernières Nike en cour de récré on passe pour un ringard à qui plus personne ne veut parler. Angoisse permanente de l'ado moderne. C'est le côté agaçant, "fashion victim", la mode pour la mode, écervelée. Pourquoi ? Parce que la mode sans un vrai concept n'est rien.

La force du concept

Tout est concept, la réalisation n'est finalement que le passage obligé pour donner corps à un concept. Un compositeur quand il possède le concept, l'idée d'une nouvelle oeuvre, n'a pas besoin de savoir écrire des partitions ni même de savoir jouer d'un instrument. Le vrai acte de création est purement intellectuel. C'est un pur concept. Mais pour le communiquer à ses semblables il lui faudra passer par la réalisation. Souvent d'ailleurs un compositeur fera appel à un arrangeur pour tout ou partie de son oeuvre. Par exemple quelqu'un qui est spécialisé dans les parties de violons ou dans celles des cuivres. Tout le monde n'est pas Mozart, ce qui n'empêche pas des tas de compositeurs d'être connus et reconnus. Pour les films il en va de même. L'auteur n'est que rarement le réalisateur, et encore moins souvent le dialoguiste. Cela enlève-t-il de la valeur à son manuscrit sans qui le film n'existerait pas ?

Le passage au tout conceptuel est justement l'apanage de l'art contemporain. Certains y voient une fumisterie car ils n'ont pas compris qu'ici la cassure a eu lieu : la réalisation n'est que la partie visible de l'iceberg, l'essentiel de l'oeuvre se trouve dans le ... concept. C'est pourquoi le bonhomme à tête carré dessiné par votre fils de 5 ans n'a aucune valeur autre que sentimentale alors que celle d'un Picasso s'arrache à coup de millions de dollars (même si ici la spéculation purement financière vient gâcher toute la beauté de l'art, mais c'est encore un autre sujet!). Picasso n'est pas un handicapé moteur ne sachant pas faire mieux que des têtes carrées, il dessine à merveille, comme un Dali ou un Miro. Mais il a choisi de casser le moule, de s'exprimer autrement en échappant au carcan normatif, et pour cela il a beaucoup réfléchit ! Le changement est principalement et purement conceptuel, bien avant d'être dans le geste du pinceau sur la toile.

Une autre représentation du monde

Revenons à notre application bancaire. Que c'est triste comme sujet... Même relooké sous Blend, que cet étalage de chiffres sera rébarbatif. N'y-a-til pas moyen de casser le cadre, d'échapper au carcan normatif ? Ne peut-on pas ajouter quelques grammes de douceurs dans ce monde de brutes ? Un poil de poésie ?

Si, cela est possible. A condition de re-conceptualiser le rapport homme / machine, et donc les interfaces.

Un peu de poésie

Très honnêtement la bourse n'est pas un sujet qui m'inspire beaucoup de poésie mais faisons un effort !

Dans notre exemple chaque action se singularise par un nom, une quantité possédée, un cours et par un indicateur signalant si elle est surveillée ou non.

Transformons ces données en acteurs. Car le changement conceptuel est en partie là. Chaque action sera ici un acteur autonome. Ne nous reste plus qu'à choisir comment cet acteur sera représenté et dans quel univers on va le faire vivre.

Par contraste choisissons un cadre naïf à l'opposé du monde de la finance : une scène champêtre. Notre décor sera une clairière avec une forêt en arrière plan. La tendance du CAC40 ? Nous allons la représenter par le temps qu'il fait : ciel bleu neutre quand l'indice est stable, soleil caniculaire lorsque que l'indice dépasse un certain pourcentage de hausse par rapport à la veille, pluie voire tempête lorsque l'indice se casse la figure.

Voilà déjà une information conventionnelle et rébarbative représentée d'une autre façon, non conventionnelle. Imaginez-vous un écran géant, quelque part sur un mur du bureau. Un joli décor de campagne animé. Quelques nuages arrivent dans le ciel. L'oeil averti de l'utilisateur saura que le CAC40 est en baisse légère. Avec l'habitude, en comptant les nuages dans le ciel il saura même dire de combien de pourcent. Tout cela sans datagrid ni alignement de chiffres....

Mais poussons plus loin les choses et intégrons les actions à ce paysage.
Supposons que chaque action soit représentée par un animal qui va évoluer dans le décor.
Total, ce goinfre, sera peut-être representé par un sanglier fouillant le sol. Air France sera représenté par une libellule, les Ciments Lafarge par un castor, etc. Maintenant appliquons à ses animaux des comportements en fonction des données chiffrées. Le nom n'est plus une donnée à affichée, le caractère choisi pour chaque action est une identité. Une donnée de moins à afficher. La quantité d'action sera représentée par la position de l'animal : à l'avant-plan quand on possède beaucoup d'action de ce type, loin quand on en possède peu. Encore une colonne du data grid qui devient inutile. Le cours est-il à la hausse ou la baisse que l'animal aura un comportement joyeux, bondissant dans le décors, ou bien qu'il semblera mou, figé, voire couché sur le flanc au sol. Plus besoin de datagrid !

Et le caractère actif/inactif de la surveillance d'une action ? Imaginons un enclos dans le décor. Par simple Drag'drop (avec le doigt comme sur Surface) prenons un animal et posons-le dans l'enclos. Le logiciel interprètera cela comme l'exact effet d'une case à cocher "surveillance active" qui sera décochée. Reprendre l'animal et le sortir de l'enclos aura l'effet inverse.

Une idée folle ?

Fermez les yeux et imaginez ce tableau vivant un instant... Une scène de campagne avec des petits animaux qui se promènent, le temps qui change, ah, tiens, une éclaircie. Le pauvre castor a l'air bien malade se matin...

Bien entendu, certains voudront savoir ce que j'ai fumé aujourd'hui, c'est un risque que j'ai pris et que j'assume en écrivant ce billet :-)

Mais ce que nous venons de faire ici est de transformer une application rébarbative qui, dans le meilleur des cas aurait été rendu sous la forme de tableaux de chiffres aux coins arrondis servis par quelques boutons animés et une poignée de drop shadow, en une scène champêtre, charmante. Quelque chose qui donne envie de regarder le programme fonctionner juste pour le plaisir. Car les données sont devenues des acteurs, car le cadre du programme est devenu un univers auto-suffisant.

La cassure est là

Plus de cases à cocher, plus de colonnes de chiffres, plus rien de normatif ni conventionnel. Les données sont des acteurs autonomes qui racontent une histoire.

Est-ce si fou ?

Il est évident que l'exemple que j'ai pris des cours de la bourse et sa représentation gentillement niaise façon Walt Disney est un simple contrepied volontairement ironique, mais pas seulement. Imaginez-vous encore ce joli tableau dans le bureau d'un riche spéculateur... Ne pensez-vous pas que je pourrais vendre des installations complètes, très cher, et que cela marcherait ? Certainement que si. Alors que personne ne voudrait acheter le énième logiciel de gestion de portefeuille que je pourrais écrire, même relooké sous Blend ! Certains même parleraient alors de snobisme, de gadget. Ceux qui ne pourraient s'offrir mon système bien entendu. Mais pas les utilisateurs qui l'achèteraient et qui en seraient très contents ! La "mode" serait lancée !

Ce qu'il faut donc comprendre ici c'est que les "nouvelles interfaces utilisateurs" l'UX (User eXperience), ce nouveau paradigme dont je parle ici bien souvent et depuis un moment maintenant, n'est pas "qu'une mode", c'est un changement conceptuel, donc en profondeur, du rapport entre l'homme et la machine. C'est une nouvelle façon de penser les données non plus comme des informations passives mais comme des acteurs autonomes évoluant dans un univers vivant.

Et concrètement ?

Tout cela est bien gentil, mais certains se disent (les plus courageux, ceux qui sont arrivés jusqu'à cette ligne ! - merci au passage :-) ) que bon, ils ont un soft à faire pour hier et qu'ils voient mal comment tout ce gentil délire peut s'appliquer à une compatibilité analytique ou une facturation.

Je leur répondrais que si j'ai pu tranformer, même virtuellement dans ces lignes, une application de gestion portefeuille boursier en une scène de campagne tout peut être fait !
Pourquoi ne pas transformer les comptes clients en bulles de couleurs évoluant dans un aquarium, plus la bulle est grosse plus l'encours du client est important, ou bien pour les commerciaux, plus la bulle devient grosse plus il est temps d'appeler le client car il n'a pas passé de commande depuis longtemps. Quelques jolis écrans plats sur les murs du service commercial ou dans le bureau du patron permettraient immédiatement de suivre la vie de l'entreprise, sans chiffres, sans cases à cocher ni boutons radio, sans fenêtre aux coins ronds ou non...

Application exemple

Dans mon temps perdu (autant dire pas grand chose) je suis en train de faire une petite application Silverlight qui met en pratique ces concepts pour faire comprendre comment on passe de mes explications à un vrai logiciel qui fait quelque chose de réel. Le code C# de l'application est déjà écrit et testé, c'est bien entendu le look qui prend le plus de temps dans un tel cas. Des mock-up en 3D, du sketching sur des bouts de papier, des dessins sous Expression Design, il me reste à mettre tout cela en forme sous Blend.

Un autre exemple existe depuis quelques années, il n'est pas logiciel mais bien du domaine informatique tout de même : le lapin Nabaztag. Tiens, il baisse l'oreille gauche... le CAC 40 se casse la figure. Ah, il devient rouge, ma chérie a laissé un message sur mon répondeur... Le créateur du Nabaztag a tout compris de cette cassure conceptuelle et des nouvelles interfaces utilisateur...

Si le sujet vous intéresse, et pour voir prochainement une illustration de ce que je viens d'expliquer ici, alors une seule solution :

Stay Tuned !

Code source Silverlight 'les codes postaux'

Il y a quelques temps j'avais mis en ligne l'application exemple Codes Postaux Français sous Silverlight. Application Silverlight 2.0 montrant l'utilisation d'un service Web avec base de données.

Beaucoup de lecteurs m'ont demandé si le code source était disponible, ce qui n'était pas le cas. J'avais prévu d'écrire un article se basant sur ce code mais le temps passant vite sans pouvoir mener à bien cette écriture j'ai opté pour une publication du code source complet, brut de fonderie.

Vous trouverez le lien de téléchargement sur la page suivante : https://www.e-naxos.com/Blog/page/Exemples-Silverlight

Silverlight 3 : Un média player complet bien caché !

Silverlight 3 est livré de base avec un contrôle très versatile, MediaElement, capable de jouer de nombreux formats comme les mp3 ou les vidéos.

Si ce contrôle est très puissant il est un peu "nu" de base et il faut soi-même ajouter les boutons de commande comme "play" et looker l'ensemble. Avec Expression Blend 3 c'est un jeu d'enfant. Enfin, de grand enfant qui a un peu de temps devant lui tout de même. D'où la question : n'existerait-il pas un MediaElement déjà tout habillé ?

Si vous possédez Expression Media Encoder 3 vous savez que cet extraordinaire outil (servant principalement à encoder des médias) donne le choix entre plusieurs formats de sortie dont des projets HTML tout fait intégrant un média player tout looké, et mieux encore, avec le choix parmi de nombreux modèles.

Quel rapport entre Media Encoder et un projet Blend/VS ? C'est tout simple : lorsque vous installez Media Encoder, sous Blend 3 dans l'onglet Assets vous disposez, en plus de MediaElement d'un nouveau contrôle "MediaPlayer" !

Par défaut ce composant ressemble à l'image ci-dessous. Pour le relooker, il suffit de faire un clic droit et d'éditer un copie du template !

Reste la question à 10 centimes d'euro : oui mais Media Encoder est livré avec de nombreux modèles dont certains ont déjà un look sympa, ne pourrait-on pas récupérer ces modèles au lieu de templater à la main le MediaPlayer ?

Si, c'est possible (© Les Nuls, "Hassan Cehef").

Comment ? Là c'est plus cher... Non, comme je suis un chic type, voici la solution gratuite :

Encoder 3 s'installe avec le code source des modèles qui se trouvent dans le répertoire "C:\Program Files\Microsoft Expression\Encoder 3\Templates\en", il suffit donc de piocher le modèle qu'on désire utiliser, et grâce aux sources d'extraire le contrôle avec son template et de l'intégrer à son propre projet !

Le célèbre Tim Heuer décrit (en englais) la méthode à suivre, je vous renvoie ainsi à son billet Using Encoder Templates in your Silverlight Application si jamais vous n'arrivez pas à vous dépatouiller seul avec le code source des projets Encoder 3.

Intégrer de la vidéo, même HD, dans une application Silverlight n'a jamais été aussi simple... et beau.

Amusez-vous bien, et .. Stay Tuned !

Silverlight 3 : un Behavior ajoutant un effet de reflexion (avec les nouvelles WriteableBitmap)

Dans le précédent billet je vous proposais d'écrire un Behavior effectuant une rotation animée d'un élément visuel, aujourd'hui je vous invite à la réflexion...

Je veux parler de l'effet de réflexion tant à la mode. WPF sait parfaitement le faire grâce notamment au brosses visuelles qui permettent facilement de "peindre" un contrôle avec la copie visuelle d'un autre objet (ou arbre d'objets). Hélas, Silverlight 3 ne possède pas encore de brosse de ce type et pour obtenir l'effet désiré il faut dupliquer le ou les objets sources et leur faire subir une rotation, un flip, et l'ajout d'un masque d'opacité. Tout cela est assez fastidieux il faut bien l'avouer.

Mais grâce aux Behaviors il est possible de rendre tout cela automatique et avec l'aide des WritableBitmap il n'est même pas nécessaire de dupliquer tous les objets !

J'ai déjà détaillé dans le billet précédent la technique de création d'un Behavior, je vous renvoie ainsi à cet exemple pour la base. Pour l'effet de réflexion, le mieux est de regarder ci-dessous l'exemple live :

[silverlight:source=/SLSamples/Reflection/ReflectionBehavior.xap;width=424;height=294]

Pour créer cet effet nous allons utiliser une nouvelle classe de Silverlight 3 : les WritableBitmap. Cette classe permet de créer des images de toute pièce ce qui n'était pas possible jusqu'à lors.

Non seulement les WritableBitmap permettent de créer une bitmap par code, mais en plus elle possède une méthode de Render qui est capable de faire le rendu de tout objet ou arbre visuel et de le placer dans la bitmap. Nous allons utiliser cette possibilité pour remplir une bitmap à laquelle nous appliquons ensuite quelques transformations (renversement, échange gauche/droite, translation). Un masque d'opacité est ajouté pour l'impression de dégradé d'opacité.

Le Behavior fonctionne sur des sources de type Canvas uniquement, cela permet d'illustrer comment limiter un Behavior à une classe ou une branche de classes donnée. Une fois l'image du reflet créé elle est ajoutée en tant qu'élément au canvas (après avoir pris soin de supprimer la précédente image s'il y en a déjà une).

Le Behavior n'a pas de rendu en mode design sous Blend 3, c'est un petit défaut. De même l'effet de réflexion est créé une fois pour toute et n'est modifié que si le canvas source voit sa taille changée. Si vous créez dynamiquement des objets sur celui-ci, le reflet ne changera pas. Bien entendu on pourrait penser connecter le Behavior à l'événement de rendu du canvas LayoutUpdated. Cela eut été une solution élégante. Hélas on créerait une boucle infinie puisque notre Behavior ajoute un objet au canvas ce qui déclenche le renouvellement de son rendu. On pourrait améliorer les choses en ne faisant pas le rendu dans le canvas source et en ajoutant une propriété au Behavior qui serait un objet de type Image (non enfant de la source) qu'on utiliserait comme sortie de rendu de l'effet de reflet. Mais cela poserait d'autres problèmes. 

Toutes les idées sont envisageables et le code proposé n'est qu'un exemple. A vous de l'améliorer sans oublier de venir ici nous dire ce que vous avez fait !

Côté paramétrage le Behavior permet de modifier les points de départ et d'arrivée du dégradé du masque d'opacité ainsi que l'offset sur l'axe Y. Sans ce dernier le reflet serait collé au canvas source ce qui n'est pas forcément très beau. Par défaut un décalage de 3 pixels vers le bas décolle légèrement le reflet de l'original.

Code la publication d'un code un peu long n'est pas forcément très lisible sur le blog, je vous renvoie au code source du projet complet que vous n'avez plus qu'à télécharger ici : ReflectionBehavior.zip (62,91 kb)

Et Stay Tuned !

 

Silverlight 3 : Ecrire des Behaviors (composants comportementaux)

Blend 3 est une version majeure de ce puissant outil qui permet de travailler le visuel d'une application WPF ou Silverlight. Blend 3 tend vers une plus grande simplicité de manipulation notamment pour les infographistes qui ne veulent / peuvent s'investir dans du code trop complexe.

Les notions de Behaviors (comportements), Actions et Triggers (déclencheurs) sont soient nouvelles pour ce qui est de la première, soit sont renforcées pour les secondes. Le but étant bien de pouvoir ajouter du comportement visuellement sans programmation. Avec les outils d'il y a 15 ans comme VB Microsoft inventait la notion de composant visuel qui se place sur une fiche par Drag Drop. Un bon en avant  quand on connaît les méthodes qui ont précédé et quand on sait avec le recul quel succès a eu cette technologie et ses clones (EDI Delphi ou Java...) ! Avec Blend 3 Microsoft innove encore dans une voie qui trace forcément ce que sera l'avenir : le "composant comportemental". On applique le "RAD" (mot plus très en vogue mais qui garde tout son sens) non plus seulement au visuel mais aussi au code.

Aujourd'hui je vais vous parler des Behaviors (comportement).

Qu'est qu'un Behavior ?

Un Behavior est un comportement, c'est à dire un bout de code qui peut faire à peu près n'importe quoi. Avec ça, vous êtes bien avancé allez-vous dire ! Mais imaginez tout ce que peut faire un bout de code autonome (ne dépendant pas d'états externes) et faites un joli paquet cadeau autour afin qu'il apparaisse dans une palette, comme un composant visuel et vous obtenez un Behavior. Un Behavior est donc avant tout une sorte de code snippet qui porte un nom et qui est listé dans Blend comme le sont les composants. Un Behavior n'existe en renvanche pas par lui-même, comme un composant Rectangle ou Button par exemple. Un Behavior s'accroche à un composant existant et c'est en jouant le poisson pilote vis à vis de ce composant qu'il lui amène le fameux comportement.

Un petit exemple pour clarifier : Imaginons qu'on souhaite pouvoir déplacer un objet par Drag Drop, il faudra gérer le mouse Down, le mouse Up et le mouse Move selon un scénario classique que je ne développerai pas. Imaginons maintenant que nous souhaitions apporter le même comportement à un autre objet. Il faudra programmer aussi tous ces événements. Si maintenant nous encapsulons tout cela dans un Behavior, il suffira de déposer le dit Behavior sur tous les composants qui, ipso facto, disposeront du comportement. La réutilisation du code est totale. Côté utilisation de Blend cela permet même de développer une application sans être développeur pour peu qu'on dispose d'une bonne bibliothèque de Behaviors, d'Actions et de Triggers (je reparlerai des deux derniers dans de prochains billets).

Créer un Behavior

Créer un nouveau Behavior est aussi simple que de créer une nouvelle classe dérivant de Behavior<T>. Il faut néanmoins à trouver la classe mère... Elle se cache dans un assembly qui n'est pas référencé de base et qui joue un peu à cache-cache... Avec la finale de Blend 3 il s'agit de :

C:\Program Files\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\Silverlight\System.Windows.Interactivity.dll

Une fois la classe créée, il ne reste plus qu'à surcharger deux méthodes : OnAttached() et OnDetaching(). C'est à partir de là qu'on peut programmer le comportement. Le Behavior peut connaître l'objet auquel il est attaché : AssociatedObject.

Un Behavior Exemple : RotateBehavior

Pour illustrer le propos j'ai cherché quel genre de petit Behavior je pourrais bien développer. Les classiques du genre ne me disait rien (faire en flou quand la souris entre sur l'objet, ou bien changer sa transparence, etc). Mais, restons réalistes, pour un petit exemple on ne pouvait faire beaucoup plus compliqué. Je me suis donc dit, tiens, une transformation du type rotation, je n'ai pas encore vu, et mieux, avec une animation pour tout de même pimenter la chose...

[silverlight:source=/SLSamples/Behavior/Behavior_base.xap;width=460;height=210]

Dans l'arbre des objets on peut voir le RotateBehavior accroché aux rectangles et à l'objet texte :

 

De même, pour le behavior sélectionné on peut voir les propriétés suivantes :

 

On note la propriété Angle, en degrés, et la propriété Duration qui définit la longueur de l'animation. Bien entendu, chaque RotateBehavior placé sur chacun des objets est paramétrable de façon séparée.

Le code exemple

Le blog est parfait pour publier des extraits de code mais pas des listing entiers. Du coup, plutôt que de vous imposer une lecture difficile, je vous propose de télécharger le projet exemple à ouvrir sous Blend 3 ou Visual Studio 2008 + SL3 SDK: Behavior_base.zip (61,84 kb)

Amusez-vous bien avec les comportements, et Stay Tuned !

WPF : Qui l'utilise ?

Après plusieurs années de présence et de maturation, WPF a plus que largement prouvé sa capacité à produire des applications riches et esthétiques. Et si la supériorité technique de WPF sur les Windows Forms ou apparentés est une évidence, une question revient très souvent : Mais qui utilise WPF ?

En effet, les applications développées en WPF sont, il faut l'avouer, plus rares que celles en Windows Forms. J'ai de longue date milité pour que cet état de fait change, et je continuerai à la faire (voir par exemple mon article sur les 10 bonnes raisons de préférer WPF et 9 raisons de plus d'utiliser WPF!). Mais ne s'est il vraiment rien passé ? Heureusement non !

Il est vrai que les interfaces séduisantes de WPF vont un peu de pair avec le nouveau look de Windows Vista. Hélas cette mouture de l'OS n'a pas rencontré le succès et la partie a été remise. En fin d'année Windows 7 viendra malgré tout enfoncer le clou. Et là, comme je vous le clame depuis longtemps, il sera juste un peu tard pour vous y mettre, WPF c'est beau, c'est puissant, mais on ne l'apprend pas un matin pour commencer un nouveau projet l'après midi... Ce n'est pas juste une nouvelle librairie d'affichage. Les principes de fonctionnement, les outils (comme Blend), tout est radicalement différent et demande une phase d'apprentissage qui ne peut être niée ni balayée d'un haussement d'épaule. Et je peux vous assurer que les projets que vous commencez aujourd'hui en Windows Forms et que vous testez joyeusement sur votre Windows XP, lorsqu'ils arriveront entre les mains de vos utilisateurs sous Windows 7 l'année prochaine (ou dans 2 ans, vous ne développez pas des softs-kleenex non ?) tous vos softs Winfows Forms auront le même air dinosauresque et désuet qu'une application console...

Bref mettez vous à WPF. Si vous préférez, formez vous en partant de Silverlight. Les bases sont les mêmes et il est vrai que Silverlight a un côté plus "exitant" pour certaines personnes (moi par exemple!). Mais l'un ou l'autre, il est temps de mettre les bouchées doubles !

Microsoft a sorti une petite brochure qui montre les principales applications WPF qui sont ou qui font sortir. De Intel à AMD, de BMW à AutoCad, regardez le look des applis que vos utilisateurs auront sur leur bureau juste à côté des vôtres en Windows Forms... Prenez du recul et, sincèrement, tiendrez-vous la comparaison ? ... Je ne le crois pas.

Voici quelques liens pour bien commencer :

Ce ne sont que quelques points de départ, il y en a bien d'autres dans mes billets mais vous les avez déjà trouvés si vous êtes un lecteur fidèle...

Bonne lecture, et Stay Tuned !

WPF et Silverlight : composants orientés données dans les Toolkits

Trouver des ressources sur les technologies ou outils récents est toujours difficile. Par force, et c'est une Lapalissade, ce qui est plus connu est plus facile à connaître, et vice versa...

Le WPF Toolkit ainsi que Silverlight Toolkit sont des mines de composants ayant beaucoup de choses en commun : même base de code, évolutions rapides et donc releases fréquentes avec à chaque fois des ajouts d'importance. Suivre le ryhtme pourrait réclamer un job fulltime...

Voici un post de Delay's Blog qui résume les dernières ressources autour de la visualisation des données dans ces deux Toolkit : http://blogs.msdn.com/delay/archive/2009/07/19/my-new-home-page-enhanced-updated-collection-of-great-silverlight-wpf-data-visualization-resources.aspx .

Visualiser les données est essentiel à toute application de type gestion, et l'avalanche de nouveautés dans les Toolkits ciblant ce besoin permet désormais d'envisager sérieusement de créer de "vraies" application avec WPF et Silverlight. Par "vraies" j'entends des applications telles que nous en concevons tous régulièrement, et non des petits jeux ou des caroussels tournoyants qui font de magnifiques démos ou des sites Web publicitaires mais qui ne sont pas forcément des applications représentatives du travail habituel d'un développeur. Il est donc d'autant plus important de connaître ces extensions de WPF et de Silverlight et pour ce faire il faut trouver les bonnes explications...

A lire absolument donc, pour y piocher des articles, des astuces, ou de simples explications sur toute la partie affichage des données sous Silverlight ou WPF.

Avec ça, vous pouvez vous occuper jusqu'à la rentrée de septembre !

Mais Stay Tuned, car j'ai plein d'autres choses à vous dire d'ici là !

Créer un arbre des répertoires avec XML (et l'interroger avec LINQ to XML)

Pour les besoins d'un prochain billet je voulais obtenir une structure arborescente de test sous la forme d'un fichier XML. Une telle chose peut se faire à la main mais cela est fastidieux et à force de copier/coller les données seront trop semblables et donc peu utilisables pour des tests et du debug, ce qui est dommage puisque tel était le but recherché...

Pour générer des données aléatoires mais réalistes je possède déjà un outil fantastique (puisque c'est moi qui l'est fait :-) ), DataGen, un logiciel puissant mais qui n'est pas étudié pour générer des données dont la strucuture est récursive. Restait donc à concevoir un utilitaire pour satisfaire mon besoin de l'instant.

Je n'aime pas développer "pour rien" donc il fallait que cet utilitaire en soit bien un. Tout disque dur de développeur contient une telle quantité de données que l'ensemble des répertoires forment une superbe structure arborescente ni trop petite ni trop gigantesque. Exactement ce qu'il faut pour des tests ! Ainsi, l'outil devra fabriquer un fichier XML à partir de n'importe quel niveau de répertoire, la structure étant hiérarchique.

Je m'empresse donc de vous faire partager ce petit bout de code qui vous sera utile un jour ou l'autre je pense.

using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
 
namespace Enaxos.Tools.Xml
{
    /// <summary>
    /// This class can generate an XML file from a folder hierarchy.
    /// </summary>
    public static class DirToXml
    {
        /// <summary>
        /// Builds the tree document.
        /// </summary>
        /// <param name="dirname">The name of the starting folder.</param>
        /// <returns>a LINQ to XML <c>XDocument</c></returns>
        public static XDocument BuildTreeDocument(string dirname)
        {
            return new XDocument(new XDeclaration("1.0", "utf-8", "yes"), 
                new XComment("Structure au "+DateTime.Now),new XElement("directories", BuildTree(dirname)));
        }
 
        /// <summary>
        /// Builds the tree (recursive method).
        /// </summary>
        /// <param name="dirName">Name of the starting folder.</param>
        /// <returns>a LINQ to XML <c>XElement</c> being the root (or 1st item) of the tree.</returns>
        public static XElement BuildTree(string dirName)
        {
            var di = new DirectoryInfo(dirName);
            var files = di.GetFiles();
            var dirsize = 0l;
            foreach (var file in files)
            {
                dirsize += file.Length;
            }
            var subdirs = di.GetDirectories();
            // each item is a "directory" having 5 attributes
            // name is the name of the folder
            // fullpath is the full path including the name of the folder
            // size is the size of all files in the folder (in bytes)
            // files is the number of files in the folder
            // subdirs is the count of possible sub directories in the folder
            var elem = new XElement("directory", 
                new XAttribute("name", di.Name), 
                new XAttribute("fullpath",dirName),
                new XAttribute("size", dirsize),
                new XAttribute("files",files.Count()),
                new XAttribute("subdirs",subdirs.Count()));
            foreach (var dinf in subdirs)
            {
                var elemDir = BuildTree(dirName + "\\" + dinf.Name);
                elem.Add(elemDir);
            }
 
            return elem;
        }
    }
}

Ce code peut être utilisé sans passer par un fichier disque puisqu'on récupère le document en mémoire. L'exemple ci-dessous montre comment appeler le code et comment interroger la structure via Linq To Xml pour connaître les répertoires vides (n'ayant ni fichier ni sous répertoire) :

   1:  var d = DirToXml.BuildTreeDocument(@"D:\WpfToolkit");
   2:  d.Save(@"d:\test.xml");
   3:  Console.WriteLine(d.ToString());
   4:  Console.WriteLine(new string('-',60));
   5:   
   6:  var q = from e in d.Descendants("directory")
   7:          where (int) e.Attribute("files") == 0
   8:               && (int)e.Attribute("subdirs") == 0
   9:               orderby (string) e.Attribute("fullpath")
  10:               select e.Attribute("fullpath");
  11:   
  12:  Console.WriteLine("Répertoires vides");
  13:  foreach (var element in q)
  14:    { Console.WriteLine(element); }
  15:  Console.WriteLine(string.Format("{0} répertoires vides",q.Count()));

 

A bientôt pour un prochain billet, so.. Stay Tuned !

Silverlight 3: Accélération GPU et cache image

Dans un récent billet sur les Pixel Shaders (effets bitmap) j'avais, par un raccourci de pensée un peu rapide, associé trop facilement les capacités d'accélération graphique GPU de Silverlight 3 avec celles de WPF. Or il existe des nuances très sensibles entre les deux implémentations.

Par souci de rigueur j'ai modifié le billet original en lui ajoutant les précisions nécessaires mais les corrections de billets ne sont pas propagées par feedburner qui gère une parite des flux RSS des abonnés à mon blog. Et pire, ceux qui ont déjà téléchargé le billet sous Outlook ou un autre news reader n'ont aucune chance de voir la correction. Ne reste plus qu'à créer un nouveau billet pour m'assurer que l'info est passée.. Voici la notice ajoutée au billet cité plus haut :

--extrait--

Quelques mots sur l'accélération GPU : Même si ce n'est pas le sujet du présent billet, il s'agit d'une nouvelle feature très intéressante de SL3. On a tendance hélas (et j'ai été le premier à me faire "avoir") à trop vite faire le parallèle avec WPF et à transposer ce que fait l'accélération sous ce dernier. En fait, le support de l'accélération GPU de SL3 est pour l'instant assez limité et ne se met en route que de façon volontaire. Elle ne s'applique pas aux effets bitmaps ni aux nouveaux flux vidéos qui restent traités par le CPU.

Malgré tout le système d'accélération graphique peut rendre d'immense service, dans certains de mes tests sur l'animation d'images assez grandes j'ai pu voir mon PC passer de 88% d'utilisation CPU (double coeur Asus plutôt rapide) à moins de 4% ! Ce qui est énorme. Mais pour profiter de l'accélération il faut aboslument en connaître le fonctionnement et les limitations.

Je vous invite ainsi à lire l'excellent billet de Andras Verlvart sur la question. Il est assorti d'une application exemple en live qui permet de bien voir l'effet des différentes possibilités d'accélération et leur impact sur le CPU et le GPU. Cet article est en anglais, pour ceux qui préfère la lecture en français, David Rousset a écrit un billet qui fait le point sur cette même question.

--fin d'extrait--

Espérant ainsi avoir rétabli la précision technique nécessaire à propos de cette nouvelle possibilité de Silverlight 3, et incidemment, vous avoir donné envie de vous familiariser avec et de l'adopter dans vos développements,

Stay Tuned pour d'autres nouvelles !