Dot.Blog

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

Easy DataGen, puissant, gratuit et online !

Un peu de teasing ne faisant jamais de mal j’ai le plaisir de vous annoncer la mise en ligne dans les semaines à venir de Easy DataGen X.

Des données aléatoires réalistes

DataGen, vous connaissez certainement, c’est mon générateur de données aléatoires – mais réalistes – vendu depuis des années sur le site e-naxos (voir la page DataGen).

Le succès de ce logiciel imposait sa refonte. La version actuelle étant Win32 réalisée d’ailleurs sous Delphi (la première release interne ayant été écrite sous ce langage en 2000/2001, une époque où WPF ou Silverlight n’étaient que des projets…).

Un outil indispensable

Ce type d’outil est totalement indispensable. Créer des grappes d’objets ou remplir des tables pour tester un logiciel en cours de conception ou faire des tests de tenue de charge est une obligation !

Mais pour beaucoup d’informaticiens ou de petites équipes cela ne justifie pas toujours l’achat d’une licence. Il est vrai que lorsqu’on doit générer 1000 enregistrements de test pour une seule table deux fois par an, même si le tarif de DataGen est particulièrement attractif, il est n’est pas toujours évident de sauter le pas de l’achat. Ainsi seules de grandes structures (grosses SSII, administrations…) n’hésitent pas à investir dans de tels outils, habituées à acquérir des logiciels améliorants la productivité et la qualité.

Une refonte Web Silverlight en accès gratuit

C’est pourquoi j’ai longtemps attendu que la technologie ait enfin évolué de façon radicale avant de refondre DataGen. Refaire un DataGen en Windows Forms n’apportait rien sur la version Delphi (ou trop peu). Refaire DataGen uniquement sous WPF obligeait les clients à installer un Framework .NET récent que beaucoup n’avaient pas et n’ont pas toujours, même aujourd’hui.

La solution est venue de Silverlight, bien entendu. Il a néanmoins été nécessaire d’attendre la version 3 pour commencer les premières études de faisabilité.

Toutefois développer un tel logiciel uniquement en mode Web impose quelques limites (comme l’impossibilité de dialoguer directement avec une base de données installée chez l’utilisateur ce qui est un plus pour l’outil, et ce que fait la version actuelle Win32).

Deux versions : Silverlight et WPF

La décision a alors été prise d’offrir deux versions du logiciels :

  • Easy DataGen X (DataGen “facile” en version 10) qui sera accessible gratuitement via le web, sous la forme d’une application Silverlight.
  • DataGen X, la version WPF offrant la totalité des fonctionnalités, mais payante.

Pour simplifier la mise en œuvre de tout cela, Le nom de domaine et l’hébergement viennent d’être achetés et un petit écran d’accueil est déjà visible pour faire patienter le visiteur ! Le nom du site est facile à retenir : www.easyDataGen.com … plus .. easy, c’est dur à trouver !

Support Bilingue

DataGen X et EasyDataGen X seront utilisables en français ou en anglais comme la version actuelle. L’interface n’est pas seulement concernée, le fonctionnement de certains générateurs en dépend aussi. Par exemple le générateur de fausses adresses postales sait utiliser un style à l’américaine ou la française pour rendre les données plus réalistes. Il s’agit donc bien d’une fonctionnalité à part entière plus qu’une simple traduction de l’interface.

Les améliorations

Si vous lisez le descriptif de la version actuelle vous aurez une bonne idée du principe et des fonctions de base. DataGen 10 apporte malgré tout de très nombreuses améliorations : d’abord une interface moderne et encore plus facile à manipuler; un très grand nombre de générateurs encore plus puissants pour des données encore plus réalistes, plus d’aide, des automatismes rendant les tâches courantes plus aisées.

La version gratuite en ligne et la version payante seront réellement complémentaires. La première sera accessible de partout avec un accès Web, même depuis un Mac, elle sera totalement gratuite tout en proposant l’essentiel du logiciel. La version payante sous WPF offrira tout ce qu’une application desktop peut amener : l’accès direct à toute base de données pour en déduire le schéma (au lieu de saisir le schéma des tables à générer dans la version Web), la génération directe dans une base cible (au lieu de passer par un fichier XML ou texte intermédiaire pour la version Web), la prise en charge des champs Image (avec génération d’images aléatoires, non pris en charge par la version Web), le générateur C# qui permet d’écrire une fonction C# pour générer des données ultra customisées (absent de la version Web), la quantité de données générée sera illimitée dans la version WPF alors qu’elle sera limitée en taille dans la version Web, etc, etc…

Comme on le voit, les deux versions seront bien complémentaires et j’ai vraiment voulu que ces différences soient réelles et non pas artificielles et juste “marketing”.
Certes la version Web gratuite permettra de mieux faire connaître le produit et, je l’espère, de vendre encore plus de versions desktop, mais la présence ou l’absence de facilités ou de certaines possibilités est directement liée aux choix technologiques. Je n’ai coupé aucune fonction de la version gratuite dans le seul but de créer une frustration obligeant à acheter la version payante. L’une est gratuite, disponible de partout via le Web, mais avec les limites de cette technologie, l’autre est plus classique et offre toutes les options que sa nature même autorise.
Pour être totalement franc, la version gratuite servira aussi de vitrine technologique. C’est une réalisation complexe sous Silverlight, en suivant la pattern M-V-VM, et disposant d’une interface agréable. Dans ma position il est assez frustrant de réaliser des choses superbes mais pour le compte de clients qui ne souhaitent pas forcément mettre mon nom en avant mais le leur (ce qui est compréhensible). Pas de mégalomanie ici, mais juste la frustration de ne pas pouvoir montrer tout ce que je réalise. Easy DataGen X comblera, en partie, cette frustration.

Voilà… Encore quelques semaines à attendre pour la bêta de Easy DataGen et vous pourrez tester l’outil en avant-première (l’annonce de la bêta sera réservée aux lecteurs de Dot.Blog).

La version Win32, par les services qu’elle rend, est toujours en vente et le sera jusqu’à la sortie de la version WPF qui sera releasée plus tard, une fois Easy DataGen stabilisé en version RTM. Pour tous les lecteurs de Dot.Blog qui feraient l’achat de la version Win32 à partir de la parution de ce billet j’offrirai la mise à jour vers la version WPF gratuitement pendant les 2 premiers mois de sa mise sur le marché !

Ceux qui auront lu le billet jusqu’à là sans zapper seront ainsi récompensés (car je ne le redirais nulle part) …

Easy DataGen X ? Une raison de plus de … Stay Tuned !

Blocage IE avec écran multitouch sous Silverlight

Voici un cas intéressant dont je viens de trouver la solution et que je m’empresse de vous communiquer…

Les écrans multitouch ne sont pas encore légion, sauf chez quelques geeks, dont je suis. Ainsi, pour tester dans un mode proche de la réalité les applications Phone 7 en cours de développement (et faute de téléphones de ce type disponible sur le marché pour l’instant) j’ai acquis un écran 22 pouces IIYama multitouch T2250MTS. C’est très sympa, pas très cher et ça marche vraiment bien de base avec Windows 7 sans installer aucun driver (c’est à dire que Windows 7 possède déjà le fameux driver et que brancher l’USB de l’écran sur le PC suffit sans aucun pilote extérieur ni CD d’installation, c’est beau le progrès !).

L’écran est même fourni avec un stylet qui se cache dans le bas de son boitier, ce qui évite les traces de gros doigts graisseux sur l’écran ! :-)

Bref, tout cela fonctionne à merveille et du premier coup. Quand on arrive sur des zones de saisie et qu’on touche l’écran il y a même un petit symbole de clavier qui apparait pour permettre d’ouvrir un grand clavier virtuel, voire le module de reconnaissance d’écriture. On voit que Windows 7 a été conçu pour investir les Tablet PC… Vraiment cool. Seul bémol, sur un écran vertical manipuler les applis avec les doigts à bout de bras c’est vite crevant… Mais ce n’est pas pour cela que j’ai acheté l’écran, c’est pour utiliser l’émulateur de Phone 7 en mode multitouch (car tester une appli pour téléphone touch avec la souris c’est le meilleur moyen de foirer le design, les doigts sont plus gros et moins précis, il faut y penser à la conception !).

Vous allez me dire c’est quoi le rapport avec Silverlight et Internet Explorer ?

C’est tout simple.

Plantage avec Silverlight ?

Silverlight gère le multitouch. Au moment où internet exploreur se lance et affiche l’application quand je suis en  debug (sous VS ou Blend) je ne sais pas trop quel niveau de sécurité IE reconnaît (en tout cas pas Intranet local car j’ai abaisser toutes les sécurités à ce niveau et cela n’a rien changé) mais à l’activation du plugin Silverlight IE 8 s’arrête, comme planté.

Impossible de s’en sortir. Il faut aller le shooter depuis les processus de Windows ou bien stopper le debug sous VS ce qui a le même effet.

Sécurité cachée !

Et là, l’oeil averti du chasseur de bug voit passer à toute vitesse comme une petite fenêtre cachée sous IE qui, hélas puisqu’on vient de flinguer IE, disparait sans qu’on puisse la lire…

Il y a donc une question qui est posée, en modal, ce qui bloque IE 8. Il “suffit” donc d’accéder à ce dialogue.

Je n’ai pas réussi. Et si on minimise IE pour que ça ne soit plus qu’un petit carré minuscule, on ne voit pas derrière la fenêtre du dialogue… Elle ne vient donc que quand IE est shooté. Bug…

Problème numéro 1: Identifier cette fichue fenêtre.

Ca passe tellement vite que c’est illisible bien entendu.

Ruse : Utiliser l’enregistreur d’écran livré avec Expression Encoder 3 et enregistrer la vidéo du bug pour faire ensuite un arrêt sur image et lire le texte du dialogue…

Ca ne marche pas au premier essai car ça va vraiment vite. Il faut ruser encore plus en modifiant les réglages d’enregistrement de la vidéo, notamment en passant à 100 images secondes et un débit d’au moins 20.000/s.

Là, on finit par choper sur la vidéo un “fantôme” du dialogue plus ou moins opaque selon la chance qu’on a. Mais on l’a eu ! Et que lit-on ?

“Un site Web veut ouvrir un contenu Web en utilisant ce programme sur votre ordinateur” et en dessous : Nom: Composant de saisie tactile ou avec sty…, Editeur: Microsoft Windows.

Le nom du composant n’est pas complet mais on a compris de ce quoi il s’agit. Silverlight, le plugin, au moment du chargement (car la première instruction de l’appli n’est pas encore atteinte, ce que prouve le debugger) doit forcément inspecter la machine pour savoir s’il y a de la vidéo, du son, et tous les périphériques ou facilités utilisées par le plugin. Parmi celles-ci se trouve vraisemblablement le multitouch et la gestion du stylet.

C’est à ce moment que le fameux dialogue est activé pour me demander si je donne le droit ou non à ce module de s’activer. Normalement on dispose sur ce genre de dialogue d’une case à cocher permettant d’indiquer si on souhaite ne plus voir la question.

Hélas, comme IE 8 semble avoir un léger bug, ce fichu dialogue est totalement incessible, on le voit à peine quand on shoote l’application. Et encore faut-il la ruse de la vidéo pour lire de quoi il s’agit.

Comment autoriser l’application bloquante ?

Second problème alors : comment autoriser le programme en question (la gestion du stylet) alors même que le dialogue et sa case à cocher ne sont pas accessibles ?

Réponse : en plongeant dans les arcanes de la gestion de sécurité de IE 8…

Et là, ce n’est pas de la tarte… J’aime bien IE, mais ce n’est pas d’une grande limpidité dès qu’on aborde ce genre de question.

Je vous fait grâce des multiples recherches sur le Web pour arriver à trouver une réponse utilisable. Que je vais maintenant vous exposer car ça peut servir ! (et pas seulement avec un écran multitouch, je suppose que le bug du dialogue doit se voir dans d’autres cas).

Pour faire simple, IE range dans la registry la liste des programmes ayant des droits faibles ainsi que la règle d’élévation de droit qui doit être appliquée. Comment certaines applications arrivent dans cette première liste, c’est un mystère que je n’ai pas essayé d’éclaircir, ce genre de plomberie en informatique me donnant rapidement la nausée. Donc, il existe dans la registry une première liste, elle se trouve là :

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy\

C’est une liste d’ID, donc de GUID. Il faut la balayer pour lire les clés qui correspondent afin de localiser le programme dont on veut changer les droits. (La registry doit être ouverte en mode administrateur cela va sans dire).

Pour ce qui est du stylet, j’ai fini par trouver le coupable, c’est le programme “wisptis.exe” qui se trouve dans %SystemRoot%\System32. Les clés d’un ID sont AppName, le nom de l’appli, ici celui de l’exe (ce qui ne simplifie pas la recherche vu à quel point le nom n’est pas parlant), AppPath, le chemin que je viens d’indiquer et enfin Policy, un DWord codant l’autorisation.

Vous trouverez des explications ici : http://www.hotline-pc.org/mode-protege.html#

Une fois l’application localisée dans cette première liste on a la moitié de la solution. Changer la Policy à ce niveau ne semble pas avoir d’effet (immédiat en tout cas).

Il faut savoir qu’en réalité, pour l’utilisateur courant, IE stocke une seconde liste, similaire, dans une autre clé de la registry :

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Low Rights\ElevationPolicy

L’astuce consiste donc à créer une nouvelle clé dans cette liste en utilisant le GUID repéré dans la première liste puis de recréer à la main les clés, dont Policy à laquelle on donne une valeur dépendant de ce qu’on cherche à obtenir. Pour la gestion du stylet j’ai mis 3, qui semble donner le maximum de droits.

Je reviens sous VS, je lance mon appli SL, et là, Ô magie… mon appli s’affiche et IE ne pose plus l’infamante question cachée…

Et ça marche !

Problème résolu. Comme on ne peut pas dire que la solution est évidente, je pense que la partagée ici sera un jour utile à quelqu’un.

Visiteur qui tombera au hasard d’une recherche Bing ou Google sur cette page et qui gagnera quelques heures de ton précieux temps, n’hésite pas à me laisser un message, ça fait toujours plaisir ! Quant aux fidèles lecteurs de Dot.Blog, le jour “J” j’espère que vous vous rappellerez que ce billet existe !

Et pour d’autres infos le mieux c’est : Stay Tuned !

Une dernière info : Le multitouch de l'écran utilise une barrière infrarouge visiblement, c'est à dire que les doigts ou le stylet coupe une grille infrarouge invisible. Ca marche vraiment bien. Sauf qu'en cette époque estivale, les mouches arrivent ! Et dans ma campagne elles ne sont pas en retard ! Hélas quand une mouche se pose sur l'écran : elle clique ! Ce qui fiche un beau bazard parfois ! Prévoyez ainsi avec l'achat d'un écran de ce type un désinsecteur électrique qui grillera tous ces nuisibles qui prennent votre écran pour un tarmark ! Je sais ça fait un peu rire comme truc... mais le geek n'a pas que des aventures palpitantes, il doit aussi combattre, outre les bugs, les mouches et autres diptères !

Deux règles pour programmer Silverlight & WPF

Des règles et des bonnes pratiques pour développer des applications Silverlight il en existe bien plus que deux, faire croire le contraire ne serait pas honnête. Ne serait-ce que par la richesse des EDI utilisés (Visual Studio, Expression Blend, Expression Design…) il faut accumuler de l’expérience et mémoriser de nombreuses patterns pour architecturer et designer correctement une application.

Alors, en vrac, voici deux règles qui me passent par la tête et que je voulais vous communiquer:

Programmation par Templates

Sous Silverlight lâchez les vieilles habitudes. L’une de celles-ci que je rencontre souvent est celle qui consiste à se jeter sur son clavier pour créer un UserControl (ou un Control par héritage) dès qu’on a besoin d’un nouveau composant qui semble absent de la bibliothèque.

Erreur. Méthode du passé.

En effet, Silverlight et WPF impliquent des changements radicaux de mode de pensée et d’habitudes. Sous ces environnements, la majorité des besoins sont couverts par les composants existants, il “suffit” juste d’en modifier le template.

Nous sommes passés d’une programmation par héritage à une programmation par modèle (template).

Deux exemples pour bien cerner ce que j’entends par là.

Sticky Note

Prenons pour premier exemple un cas d’école, déjà ancien mais en plein dans notre propos : sticky notes pour WPF (sticky notes listbox). Ce “composant” se présente comme une liste verticale de petites notes de type “post-it” légèrement décalées les unes par rapport aux autres.

L’effet est sympathique et donne un peu de fantaisie et de vie à ce qui ne serait qu’une liste rectangulaire dans une grille en programmation classique.

Ce magnifique “composant” n’utilise aucun code “'classique”. Inutile dans les sources de chercher la classe StickyNotes qui hériterait de Control ou même de chercher dans les fichiers de l’application le UserControl créé pour l’occasion.

Rien de tout cela.

Sticky Notes est créé uniquement en jouant sur le templating d’une simple… Listbox ! Une poignée de Xaml et des templates, c’est tout.

Language button

Dernièrement dans une application Silverlight je devais implémenter un bouton permettant de choisir depuis la page d’accueil la langue à utiliser (français ou anglais). Forcément on pense à un ToggleButton ou quelque chose d’équivalent (ce qui n’existe pas de base). On pourrait aussi associer deux RadioButton dans une grille.

Mais le plus intéressant consiste à se demander “quel control existant se rapproche le plus du comportement que je souhaite implémenter”. En y réfléchissant quelques secondes on s’aperçoit assez vite qu’une CheckBox possède deux états stables (oublions ici l’état indéterminé). Ce composant comporte toute la logique et les états visuels permettant de gérer deux états.

Par défaut une CheckBox c’est une case à cocher avec un bout de texte devant ou derrière.

Le plus dur consiste à se l’imaginer comme deux drapeaux (français et US) côte à côte, celui qui est sélectionné étant à 110% de sa taille et l’autre à 50%. Par convention arbitraire et chauvinisme inconscient certainement j’ai considéré que IsChecked = True était le Français, à False l’anglais. En partant d’une CheckBox que j’ai totalement vidée de son contenu, et en ajoutant les deux drapeaux (et quelques autres ingrédients et animations via le VSM) j’ai obtenu un merveilleux “ToggleButton” sans jamais “sous-classer” le moindre contrôle. Juste en écrivant un template.

Le ViewModel de la page d’accueil offre une propriété IsFrench de type booléen qui est simplement bindée à la propriété IsChecked du CheckBox (en mode TwoWay) et l’affaire est jouée !

Règle 1 : De l’héritage au templating

La programmation Xaml (Silverlight / WPF) est une programmation visuelle qui s’effectue par templating. Créer des UserControl et encore plus sous-classer des contrôles existants devient quelque chose de rarissime.

Nous sommes passés de l’ère de la programmation objet par héritage à celle de la programmation visuelle par templating. Bien comprendre toute la signification de ce changement est un point primordial et un préliminaire indispensable pour comprendre cette technologie et donc la programmer intelligemment.

Programmation par Properties

Il s’agit du même genre de glissement, une pente douce mais dont la longueur finit par conférer une vitesse tellement grande à celui qui s’y laisse glisser que le décor n’a plus rien à voir avec celui qu’on a tout le temps d’admirer en balade à dos d’âne…

Dans l’exemple précédent on touchait du doigt cette nouvelle approche mais sans la mettre en exergue.

En effet, dans la pattern M-V-VM plutôt que de créer un code incompatible avec le visuel d’un côté pour ensuite créer de l’autre des tripotés de convertisseurs (programmation classique non M-V-VM sous WPF et Silverlight dans une moindre mesure) il semble bien plus simple d’exposer dans les ViewModels des propriétés directement exploitables par l’UI. Si adaptation des données il doit y avoir c’est le ViewModel qui s’en charge (directement si cela est ponctuel, ou via une classe de service si la chose doit être réutilisées ailleurs).

Dans l’exemple précédent du Checkbox transformé en ToggleButton de langue, aucun événement n’est programmé, aucun gestionnaire n’est écrit pour réagir au clic. Tout se joue dans le ballet automatique de IsChecked de la CheckBox et de IsFrench du ViewModel sous l’égide discrète mais indispensable d’un binding two way…

Quant l’utilisateur clique sur la CheckBox (enfin sur le ToggleButton avec les deux drapeaux) le composant sous-jacent bascule sa propriété IsChecked à vrai ou faux selon le cas. Comme cette dernière est liée à IsFrench du ViewModel, une propriété de type booléen aussi pour assurer la compatibilité des comportements, le ViewModel reçoit pas un événement mais l’une de ces propriétés (IsFrench) se voit modifiée. Ce qui déclenche le Setter de cette dernière. Ce dernier s’occupant de modifier le fichier de ressource utilisé pour puiser les chaines de caractères. De là et par une série de notification de changement de propriétés, il avertit en retour la Vue que toutes les propriétés de type texte ont été modifiées. La vue (et ses binding) y réagit en rafraichissant les affichages…

Toute cette mécanique s’est déroulée sans aucun gestionnaire d’événement, sans aucune programmation “classique” (en dehors du ViewModel et de ces propriétés gérant INotifyPropertyChanged, ce qui peut être automatisé ou simplifié en utilisant Mvvm-light par exemple).

Règle 2 :  de l’événementiel à binding

La seconde règle d’or à bien comprendre pour tirer totalement partie de Xaml et de ses enfants (Silverlight et WPF) est ainsi d’opter pour un modèle de développement de type Model-View-ViewModel se basant presque exclusivement sur des couples de propriétés mis en relation via binding.

On est passé de l’ère du développement dit “événementiel” des premières versions de Windows à ce qu’on pourrait appeler la “programmation par Binding” ou par “properties”.

Conclusion

Pour résumer :

Règle 1 on cherche à templater des contrôles existants sans créer des UserControl ni dériver des contrôles existants.

Règle 2 : on base la dynamique de l’application sur le binding entre propriétés et non plus sur les gestionnaires des événements des contrôles.

Si vous avez déjà fait vôtre ses règles alors vous allez devenir, si ce n’est pas déjà le cas, de très bons développeurs Silverlight et Xaml très recherchés !

Si vous n’aviez pas encore vu les choses sous cet angle là, je serai très heureux si par chance j’ai réussi à tirer le voile qui vous empêchait de les voir ainsi. Vous ne ferez qu’entrer plus vite dans la catégorie précédente !

Bon Dev, et, œuf corse,

Stay Tuned !

Xaml Dynamique

Xaml n’est pas compilé, ce qui signifie que le runtime l’interprète à l’exécution. Cet interpréteur est donc présent aussi bien quand on exécute une application WPF que Silverlight. Cela peut permettre des choses intéressantes comme la création de code Xaml dynamiquement au runtime…

Cette possibilité n’est que peu souvent évoquée alors que dans certains cas elle autorise de dynamiser tout ou partie d’une interface. Rien n’interdit en effet de créer une mise en page complète par ce procédé, VSM et animations comprises. La génération de Vues (partielles ou totales) en fonction d’une description paramétrée par l’utilisateur fait partie des cas concrets où de la génération dynamique de code Xaml peut grandement simplifier la mise en œuvre du code.

Le potentiel est grand, il suffit juste de savoir que cela existe car techniquement cela est finalement très simple. L’essentiel tient dans XamlReader.Load() qui sait rendre un objet à partir d’un code Xaml.

Pour sortir des sentiers battus, voyons comment on peut utiliser cette stratégie pour créer dynamiquement un composant à partir de son nom de classe non pas en utilisant la réflexion sous C#, juste en générant du code Xaml…

L’exemple live ci-dessous permet de créer un contrôle (pré-saisi par défaut pour un textBlock) qui sera ajouté dans un StackPanel dans la seconde moitié verticale de l’affichage. Créez plusieurs TextBlock de cette façon en modifiant le texte ou d’autres paramètres. Puis créez-en un auquel vous ajouterez dans les paramètres: Name=’Test’. Enfin cliquez sur le bouton “changer couleur des TextBlock”.

Tous les TextBlocks créés passeront en Foreground noir, et celui qui a pour non ‘Test’ vera sa taille de fonte augmentée de 4.

[silverlight:source=/SLSamples/DynXaml/DynamicXaml.xap;width=480;height=400]

Le code de création du contrôle est le suivant :

namespace DynamicXaml{    
public static class DynamicXamlHelper
{
public static UIElement CreateControlFromName(string controlName, 
string controlNamespace, string xmlnsPrefix, string properties)
{
var sb = new StringBuilder();
sb.Append("<" + controlName + " xmlns");
if (xmlnsPrefix.Length > 0) sb.Append(":" + xmlnsPrefix);
sb.Append("=\"" + controlNamespace + "\" " + properties + "/>");
try
            { return (UIElement)XamlReader.Load(sb.ToString()); }
catch
            {
return null;
}
}
}
}

Les paramètres sont ceux que vous pouvez taper dans les textBox de l’exemple live ci-dessus:

Pour le reste, le plus simple est jouer avec le code source de l’exemple : DynamicXaml.zip (7,08 kb)

Silverlight et le multi-thread (avec ou sans MVVM)

La “parallélisation” des traitements est devenu un enjeu majeur et paradoxal du développement et Silverlight n’échappe pas à ce nouveau paradigme.

Nouveau Paradigme ?

Nouveau paradigme, cela fait toujours un peu “attention je suis en train de dire quelque chose d’intelligent et j'utilise une tournure à la mode qui fait savante pour le faire remarquer”… Mais parfois cela a aussi un vrai sens et une vraie justification !

Nouveau paradigme donc que la programmation multitâche, ou pour être encore plus chébran, parlons de programmation parallèle, voire de parallélisme tout en évitant le trop prétentieux “massivement parallèle” (nos PC ne comptent pas encore la centaine de “cores” – plutôt que “cœurs” pour faire totalement geek – qu’Intel prévoit pour dans quelques temps).

On le sait depuis un moment, la fréquence des processeurs n’évoluera plus comme elle l’a fait jusqu’à lors. Le fondeur de processeurs se retrouve ainsi face à un mur infranchissable, un peu comme l’était le mur du son pour l’aviation jusqu’à ce jour d’octobre 47 ou le pilote Yeager à bord du Bell-X-1 finit par traverser les briques de ce mur qu’on avait cru impénétrable. Pour nous il s’agit du “mur des performances”. On miniaturise, on diminue l’épaisseur des couches, on tasse les transistors, mais on butte sur la fréquence. Le seul moyen d’aller plus vite reste de multiplier les processeurs… Et comme multiplier les cartes mères atteint vite une limite en termes de prix et de consommation électrique, on essaye désormais de tasser des cœurs sur les puces comme on tassait les transistors à l’étape précédente. Ce n’est pas une option et il n’y a pas de “plan B”, c’est la seule solution jusqu’à ce qu’existent les ordinateurs quantiques (dont la faisabilité reste totalement à prouver).

Deux, quatre, huit, trente-deux, bientôt cent cœurs dans les machines de monsieur Tout-Le-Monde. 

Hélas ce n’est pas avec les techniques de programmation utilisées jusqu’aujourd’hui que les informaticiens vont s’en sortir. Les fondeurs ont trouvé le moyen de percer le “mur des performances”, et si les informaticiens ont une idée de comment ils vont relever le défi, ils ne se sont pas encore dotés des outils permettant de le faire : une formation ad hoc et une approche radicalement différente de la programmation.

On peut ainsi réellement, et sans emphase exagérée, parler de “nouveau paradigme” de la programmation parallèle car seule cette nouvelle approche va permettre aux logiciels de bénéficier des accélérations offertes par les processeurs modernes et encore plus par ceux à venir. Et pour cela il va falloir que les développeurs se mettent à niveau alors qu’ils sont déjà à la traîne de cette révolution…

J’ai dernièrement acquis une machine à 4 cœurs hyperthreadés, donc à 8 cœurs apparents. Avec certaines applications elle va à peine aussi vite que mon double cœurs E6700 overclocké (et pas toujours)… Je regarde la jolie fenêtre des performances de Windows, je vois ces huit magnifiques graphiques qui sont autant de preuves formelles de la puissance de la bête (et un enchantement de geek), mais un seul s’active vraiment, un autre le faisant mollement, et les 6 autres piquant un roupillon désespérant ! Ces applications je les maudis et dans la foulée leurs concepteurs incompétents qui ont programmé comme on le faisait il y a 20 ans : en pensant qu’un seul processeur anime la machine et que Windows va se débrouiller pour partager le temps (et que si l’utilisateur trouve que “ça rame” il n’a qu’à acheter une machine récente…).

En revanche je suis plein de compliments confraternels à l’égard des développeurs qui ont programmé les quelques applications qui savent se servir de mes huit cœurs ! Ces programmes qui s’essoufflaient sur le E6700 deviennent des bombes sur le i870, ou, au minimum de mes attentes, vont nettement plus vite, ce qui n’est déjà pas si mal.

Faire partie de ceux qu’on maudit ou de ceux qu’on félicite, il va falloir choisir son camp !

Programmer “parallèle” devient ainsi une obligation de fait, techniquement parlant. Mais il ne faut pas ignorer non plus les cas plus classiques où le parallélisme est le seul moyen de programmer certaines fonctions. C’est ce que nous verrons dans un instant au travers d’un exemple de code.

Mais paradoxal !

En effet, ce nouveau paradigme n’en est pas moins paradoxal . La raison est simple : d’un côté les multi-cœurs se généralisent dans les PC et de l’autre l’informatique mobile explose avec des téléphones aux interfaces graphiques à faire pâlir les progiciels PC les plus chers, des iPad, des EEEPC, et autres merveilleuses petites machines ayant toutes en commun d’être dotées d’un seul processeur rikiki et monocœur !

Alors que .NET 4.0 arrive avec des dizaines de méga de couches plus sophistiquées les unes que les autres, simultanément Silverlight et son mini Framework sont annoncés (avec XNA) comme l’interface des Phones 7, voire bientôt de certaines tablettes PC…

Faire le grand écart entre ces deux tendances extrêmes et néanmoins concomitantes relève du tour de force et place l’informaticien dans une situation paradoxale. Et pourtant ce sont deux défis que le développeur doit dès aujourd’hui relever, et simultanément ! Même en s’y mettant tout de suite, il part en retard (les “utilisateurs de base” possèdent depuis plusieurs années des machines à double cœurs !). Il faut donc programmer en visant la “scalability” ou “capacité à s’adapter”, s’adapter à la charge, s’adapter au matériel. Tirer le meilleur d’un Phone 7, faire cracher ses chevaux à un PC de bureau 8 cœurs. En gros il faut maîtriser la programmation parallèle.

En pratique on fait comment ?

On sort ses neurones du mode économie d’énergie certifié Energy Star et on se sert de l’ordinateur le plus massivement parallèle de l’univers : son cerveau :-)

Cela signifie adopter une nouvelle “attitude” face à la programmation quotidienne. La moindre classe doit être pensée dans un contexte multi-tâche. Cela doit devenir un automatisme, comme de finir chaque instruction par un point-virgule en C#.

Mais comme il n’est pas question dans ce blog de faire un cours complet sur le multi-tâche, attardons-nous sur un exemple concret et voyons comment introduire un peu de ces réflexes qui tendent vers une meilleur utilisation des ressources physiques sous-jacentes offertes par la machine hôte de nos chefs-d’œuvres compilés….

Un exemple concret

programmer en vue d’une utilisation multi-tâche n’est pas forcément simple. On peut être ainsi tenter d’y échapper jusqu’au jours où on tombe sur un cas tout simple qui va déboucher sur un magnifique plantage.

Comme le titre du billet l’indique, cela n’a rien de spécifique à MVVM, même si l’exemple sera programmé dans un mode de ce type (mais très édulcoré, ce n’est donc pas un exemple MVVM, pour cela se reporter à l’article complet que j’ai écrit sur le sujet).

Imaginons ainsi une vue présentant des données issues d’un ViewModel ou directement d’un Modèle (ce que MVVM autorise). Supposons ce dernier cas pour simplifier la “plomberie” de l’exemple. Ce Modèle simule une source de données un peu particulière puisqu’elle fonctionne en permanence et dépend de données externes qui arrivent un peu quand elles veulent. Cela n’a rien d’exotique, prenez un simple Chat, il y aura bien un Modèle fournissant les messages de l’interlocuteur fonctionnant en permanence et la fréquence d’arrivée des données (les messages) est aléatoire (quand l’interlocuteur a envi d’écrire).

Le modèle

Le Modèle de notre exemple sera bien plus simple encore : il fabrique des nombres aléatoires. Mais il les fabrique dans un thread séparé qui s’endort pour une durée aléatoire après chaque génération de nombre. Pour ce faire la classe RandomNumberPusher utilise un BackgroundWorker, classe du Framework permettant assez simplement de créer des tâches de fond (code source du projet à télécharger plus bas).

la Vue

Créons une vue (la MainPage sera suffisante pour cet exemple minimaliste) et attachons une instance de la classe RandomNumberPusher au DataContext de la grille principale. Ajoutons un TextBlock bindé (voir mon article sur le Binding Xaml) à la propriété Number. Et exécutons…

Le plantage…

A intervalle irrégulier l’instance du Modèle va générer en tâche de fond un nombre aléatoire et va déclencher la notification de changement d’état de la propriété Number (événement PropertyChanged). La Vue et son TextBlock étant bindés à cette dernière, la mise à jour du texte va se faire automatiquement. Oui mais… cela va planter. Pour une raison simple : seule le thread principal ayant créé les objets d’interface peut modifier ces derniers, or le générateur aléatoire fonctionne depuis un thread différent. On peut mettre le plantage encore plus en évidence si on tentait de modifier directement la propriété Text du TextBlock depuis la tâche de fond. Le modèle de programmation MVVM nous oblige à penser le code autrement (et c’est une bonne chose) et le plantage ne se verra pas forcément (le TextBlock ne changera pas de valeur). Mais à un moment donné il risque de s’afficher ceci :

Accès inter-thread non valide. Le couperet tombe.

Pour obtenir ce message de façon sûre il faut placer un point d’arrêt dans le thread de fond, s’arrêter dessus et repartir car le plus souvent le texte n’est tout simplement pas mis à jour. Comme je le disais plus haut, le plantage serait systématique si la tâche de fond mettait à jour directement le TextBlock ce que le montage de type MVVM évite. Le bug n’en est que plus sournois car il ne se passe rien, et rien, ce n’est pas grand chose ! Sur un écran un peu chargé il sera difficile de détecter le problème durant les tests.

Le mécanisme est simple :

Le thread de fond modifie la propriété Number, ce qui déclenche l’événement de changement de propriété (PropertyChanged), l’objet de binding est alors activé et tente de mettre à jour la valeur de la propriété Text du TextBlock. La plantage résulte du fait que la modification de ce dernier est effectué au travers d’un thread différent de celui gérant l’UI.

Le code xaml

   1:  <UserControl x:Class="SLMultiThread.MainPage"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   5:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   6:      xmlns:model="clr-namespace:SLMultiThread.Models"
   7:      mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
   8:      <UserControl.Resources>
   9:          <model:RandomNumberPusher x:Key="random" />
  10:      </UserControl.Resources>
  11:      <Grid x:Name="LayoutRoot" DataContext="{StaticResource random}">
  12:          <TextBlock Text="{Binding Number, Mode=OneWay}"/>
  13:      </Grid>
  14:  </UserControl>

On note : la déclaration du namespace de notre Modèle, la déclaration d’une instance du Modèle en ressource, la définition du DataContext du LayoutRoot depuis cette dernière et enfin, le TextBlock bindé à la propriété Number.

Le code C# de la classe RandomNumberPusher n’est pas en cause dans le mécanisme du plantage. Elle est programmée en répondant aux exigences d’une classe dite Thread-Safe. Donc pour l’instant oublions là.

Les solutions

Plusieurs aspects sont à prendre en compte lors d’une programmation multi-thread. Le plantage que nous venons de mettre en évidence n’est qu’un aspect des choses, limité uniquement à la spécificité de Xaml qui ne prend pas en charge la mise à jour de l’UI via un thread autre que le principal. On trouvait déjà ce problème sous Windows Forms d’ailleurs.

Concernant ce problème spécifique il y a plusieurs approches, mais au final il n’y a qu’un moyen : faire en sorte que la manipulation de l’UI ne passe que par son thread propre. Ponctuellement on peut utiliser, comme sous Windows Forms, des mécanismes d’invocation transférant le contrôle au thread de l’UI. Mais ce que nous cherchons est une solution globale et “industrialisable”. La plupart des auteurs qui a abordé le sujet arrive à la même conclusion, il faut passer par un mécanisme centralisé de dispatch. Cette solution peut se mettre en œuvre de différentes façons, voyons directement celle qui m’apparait la plus simple à appliquer.

Le SmartDispatcher et la classe de base

Le principe peut se schématiser comme suit :

Au début les choses sont, par force, identiques : la tâche de fond modifie la propriété (Number dans notre exemple) et déclenche PropertyChanged dans le Modèle. Mais au lieu que cet événement soit traité directement par le binding, nous intercalons le Dispatcher, c’est lui qui va vérifier que l’appel a lieu depuis le thread d’UI. Dans l’affirmative le traitement se poursuivra normalement, dans la négative, ce qui est le cas de notre exemple, il transfèrera la notification de changement de propriété au binding via une invocation appropriée. Comme le Dispatcher se trouve dans le thread de l’UI, et qu’il va faire en sorte de rendre “sien” les appels qui proviennent d’autres threads, le binding ne verra que des appels intra-thread UI et non inter-threads.

Cette solution fonctionne en deux étapes. Il y a le Dispatcher, mais il y a aussi le routage des notifications vers ce dispatcher. Modifier dans chaque classe l’appel à PropertyChanged pour qu’il pointe vers le Dispatcher serait fastidieux et source d’erreur. Le plus simple est donc de créer une classe de base dont hériterons les Modèles ou les ViewModels plus généralement (la connexion directe d’une Vue à un Modèle utilisée dans l’exemple est certes autorisé par MVVM mais ce n’est pas le “montage” le plus courant, le ViewModel étant souvent nécessaire pour la prise en charge des commandes, l’adaptation des données et la persistance de la Vue).

Le mécanisme du Binding et des patterns comme MVVM reposent sur un présupposé : que les classes reliées par binding à l’UI prennent en charge INotifyPropertyChanged. Il est donc raisonnable de mettre en œuvre une classe de base implémentant cette interface et s’occupant automatiquement de la liaison avec le Dispatcher.

Le seul problème que peut poser cette approche est que le ViewModel soit déjà dans l’obligation d’hériter d’une classe de base. Cela peut être le cas si vous utilisez un framework MVVM ou autre. C# ne gérant pas l’héritage multiple (bien heureusement), il faudra alors fusionner la solution du Dispatcher à la classe de base déjà utilisée. A moins que celle-ci ne prenne déjà en charge un mécanisme équivalent, mais dans ce cas je peux aller me coucher vous n’avez plus besoin de mes conseils ! :-)

Le code du Dispatcher

Parmi les implémentations existantes j’ai une préférence pour celle de Jeff Wilcox qui est un Senior Software Development Engineer chez Microsoft dans l’équipe de Silverlight… Autant se servir aux bonnes sources ! Son implémentation est sous licence Ms-PL (licence libre publique spécifique à Microsoft). J’avais dans mes tablettes un code assez proche mais pas aussi complet et on peut trouver des choses assez équivalentes dans le portage de Cairngorm sur Silverlight (Cairngorm sur CodePlex) , un framework MVC traduit depuis l’original de même nom conçu pour Flex de Adobe (un produit proche de Silverlight pour ceux qui ne connaissent pas).

   1:  using System;
   2:  using System.Windows;
   3:  using System.ComponentModel;
   4:  using System.Windows.Threading;
   5:   
   6:  namespace SLMultiThread.ThreadTools
   7:  {
   8:      // (c) Copyright Microsoft Corporation.
   9:      // This source is subject to the Microsoft Public License (Ms-PL).
  10:      // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
  11:      // All other rights reserved.
  12:      
  13:      
  14:          /// <summary>
  15:          /// A smart dispatcher system for routing actions to the user interface
  16:          /// thread.
  17:          /// </summary>
  18:          public static class SmartDispatcher
  19:          {
  20:              /// <summary>
  21:              /// A single Dispatcher instance to marshall actions to the user
  22:              /// interface thread.
  23:              /// </summary>
  24:              private static Dispatcher instance;
  25:   
  26:              /// <summary>
  27:              /// Backing field for a value indicating whether this is a design-time
  28:              /// environment.
  29:              /// </summary>
  30:              private static bool? designer;
  31:   
  32:              /// <summary>
  33:              /// Requires an instance and attempts to find a Dispatcher if one has
  34:              /// not yet been set.
  35:              /// </summary>
  36:              private static void requireInstance()
  37:              {
  38:                  if (designer == null)
  39:                  {
  40:                      designer = DesignerProperties.IsInDesignTool;
  41:                  }
  42:   
  43:                  // Design-time is more of a no-op, won't be able to resolve the
  44:                  // dispatcher if it isn't already set in these situations.
  45:                  if (designer == true)
  46:                  {
  47:                      return;
  48:                  }
  49:   
  50:                  // Attempt to use the RootVisual of the plugin to retrieve a
  51:                  // dispatcher instance. This call will only succeed if the current
  52:                  // thread is the UI thread.
  53:                  try
  54:                  {
  55:                      instance = Application.Current.RootVisual.Dispatcher;
  56:                  }
  57:                  catch (Exception e)
  58:                  {
  59:                      throw new InvalidOperationException("The first time SmartDispatcher is used must be from a user interface thread. Consider having the application call Initialize, with or without an instance.", e);
  60:                  }
  61:   
  62:                  if (instance == null)
  63:                  {
  64:                      throw new InvalidOperationException("Unable to find a suitable Dispatcher instance.");
  65:                  }
  66:              }
  67:   
  68:              /// <summary>
  69:              /// Initializes the <see cref="SmartDispatcher"/> system, attempting to use the
  70:              /// RootVisual of the plugin to retrieve a Dispatcher instance.
  71:              /// </summary>
  72:              public static void Initialize()
  73:              {
  74:                  if (instance == null)
  75:                  {
  76:                      requireInstance();
  77:                  }
  78:              }
  79:   
  80:              /// <summary>
  81:              /// Initializes the <see cref="SmartDispatcher"/> system with the dispatcher
  82:              /// instance.
  83:              /// </summary>
  84:              /// <param name="dispatcher">The dispatcher instance.</param>
  85:              public static void Initialize(Dispatcher dispatcher)
  86:              {
  87:                  if (dispatcher == null)
  88:                  {
  89:                      throw new ArgumentNullException("dispatcher");
  90:                  }
  91:   
  92:                  instance = dispatcher;
  93:   
  94:                  if (designer == null)
  95:                  {
  96:                      designer = DesignerProperties.IsInDesignTool;
  97:                  }
  98:              }
  99:   
 100:              /// <summary>
 101:              ///
 102:              /// </summary>
 103:              /// <returns></returns>
 104:              public static bool CheckAccess()
 105:              {
 106:                  if (instance == null)
 107:                  {
 108:                      requireInstance();
 109:                  }
 110:   
 111:                  return instance.CheckAccess();
 112:              }
 113:   
 114:              /// <summary>
 115:              /// Executes the specified delegate asynchronously on the user interface
 116:              /// thread. If the current thread is the user interface thread, the
 117:              /// dispatcher if not used and the operation happens immediately.
 118:              /// </summary>
 119:              /// <param name="a">A delegate to a method that takes no arguments and
 120:              /// does not return a value, which is either pushed onto the Dispatcher
 121:              /// event queue or immediately run, depending on the current thread.</param>
 122:              public static void BeginInvoke(Action a)
 123:              {
 124:                  if (instance == null)
 125:                  {
 126:                      requireInstance();
 127:                  }
 128:   
 129:                  // If the current thread is the user interface thread, skip the
 130:                  // dispatcher and directly invoke the Action.
 131:                  if (instance.CheckAccess() || designer == true)
 132:                  {
 133:                      a();
 134:                  }
 135:                  else
 136:                  {
 137:                      instance.BeginInvoke(a);
 138:                  }
 139:              }
 140:          }
 141:  }

Le SmartDispatcher est une enveloppe intelligente autour de la classe Dispatcher du Framework de Silverlight. Cette dernière a été conçue justement pour gérer le code de mise à jour de l’UI depuis d’autres threads. SmartDispatcher “habille” le Dispatcher de base en s’assurant qu’une instance est disponible. En fait, appeler le Dispatcher de SL serait suffisant, il est conçu pour cela, mais cela n’est pas possible depuis une tâche de fond, il faut donc que l’instance existe déjà. Le SmartDispatcher permet de s’assurer de cette condition liminaire et fournit un point d’accès connu et centralisé à l’instance en question.

Bien que SmartDispatcher s’occupe d’obtenir l’instance du Dispatcher automatiquement il est préférable de l’initialiser très tôt dans le code de l’application, pour s’assurer que le SmartDispatcher est bien opérationnel et disponible avant tout événement impliquant l’interface. C’est pourquoi il est préférable d’ajouter dans App.xaml le code suivant dans le constructeur de l’objet App, juste avant l’appel à InitializeComponent() :

SmartDispatcher.Initialize(Deployment.Current.Dispatcher); 

Le SmartDispatcher est initialisé avec le Dispatcher fourni par le namespace Deployment qui s’occupe majoritairement du manifest et d’informations sur l’application en cours.

La classe de base

Il y a plusieurs façons de l’implémenter, mais puisque j’ai fait le choix de vous montrer l’implémentation de SmartDispatcher, autant utiliser la classe de base qui a été écrite par Wilcox pour fonctionner avec ce dernier, ça semble logique…

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel;
   4:   
   5:  namespace SLMultiThread.ThreadTools
   6:  {
   7:      // (c) Copyright Microsoft Corporation.
   8:      // This source is subject to the Microsoft Public License (Ms-PL).
   9:      // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
  10:      // All other rights reserved.
  11:   
  12:          /// <summary>
  13:          /// A base class for data objects that implement the property changed
  14:          /// interface, offering data binding and change notifications.
  15:          /// </summary>
  16:          public class PropertyChangedBase : INotifyPropertyChanged
  17:          {
  18:              /// <summary>
  19:              /// A static set of argument instances, one per property name.
  20:              /// </summary>
  21:              private static readonly Dictionary<string, PropertyChangedEventArgs> argumentInstances = 
  22:                  new Dictionary<string, PropertyChangedEventArgs>();
  23:   
  24:              /// <summary>
  25:              /// The property changed event.
  26:              /// </summary>
  27:              public event PropertyChangedEventHandler PropertyChanged;
  28:   
  29:              /// <summary>
  30:              /// Notify any listeners that the property value has changed.
  31:              /// </summary>
  32:              /// <param name="propertyName">The property name.</param>
  33:              protected void NotifyPropertyChanged(string propertyName)
  34:              {
  35:                  if (string.IsNullOrEmpty(propertyName))
  36:                  {
  37:                      throw new ArgumentException("PropertyName cannot be empty or null.");
  38:                  }
  39:   
  40:                  var handler = PropertyChanged;
  41:                  if (handler == null) return;
  42:                  PropertyChangedEventArgs args;
  43:                  if (!argumentInstances.TryGetValue(propertyName, out args))
  44:                  {
  45:                      args = new PropertyChangedEventArgs(propertyName);
  46:                      argumentInstances[propertyName] = args;
  47:                  }
  48:   
  49:                  // Fire the change event. The smart dispatcher will directly
  50:                  // invoke the handler if this change happened on the UI thread,
  51:                  // otherwise it is sent to the proper dispatcher.
  52:                  SmartDispatcher.BeginInvoke(() => handler(this, args));
  53:              }
  54:          }
  55:   
  56:  }

Cette classe implémente INotifyPropertyChanged qui est à la base du mécanisme de propagation “automatique” des changements de valeurs utilisé par le binding et sur lequel repose des patterns comme MVVM.

La classe utilise un astuce pour améliorer les performances : elle créée un dictionnaire des PropertyChangedEventArgs de telle façon à ce que ce soit toujours la même instance d’arguments qui soit utilisée pour une propriété donnée. Ainsi, et surtout lorsque les valeurs changent très souvent, le Garbage Collector n’est pas submergé de petits objets à durée de vie ultra-courte. Il est certes optimisé pour cela, mais moins il y a de créations / destructions moins le GC a de travail et tout va plus vite.

Une autre optimisation est importante, elle concerne la détection de la nécessité ou non de transiter via le Dispatcher. Dans le cas où cela n’est pas nécessaire le message de notification suit son cours. Il est ainsi traité immédiatement alors que le passage via le Dispatcher créé un délai (même infime).

Le code exemple

Le projet complet (VS2008 SL3) est téléchargeable ici: SLMultiThread.zip (9,55 kb)

Les autres facettes du multi-thread

Ici nous n’avons fait qu’effleurer le sujet en abordant un problème très spécifique du multithreading sous Silverlight. Si vous regardez le code de plus près, notamment la classe RandomNumberPusher que nous n’avons pas étudiée dans ce billet, vous y trouverez des techniques simples propres au mutithreading comme l’utilisation d’un objet “locker” pour assurer le verrouillage des lectures et écritures entre les threads.

Le sujet est vaste et il serait possible d’en parler des heures. Je réserve cela pour un éventuel futur article, il faut bien en laisser un peu pour plus tard… Une raison de plus de …

Stay Tuned !

WPF : Le vote du mois

Je parle beaucoup de Silverlight ici, c’est vrai que j’ai un penchant pour cet enfant de WPF. On sait aussi que ce dernier a plus de mal à s’imposer. En vrai, vous en êtes où avec WPF ?

Pour le savoir, le vote est ouvert tout le mois alors VOTEZ !
(c’est facile, juste une question, juste une réponse en un clic)

c’est ici : Votre position vis à vis de WPF ?

On fera le point le mois prochain, alors…

Stay Tuned !

Article ! Le Binding Xaml, sa syntaxe, éviter ses pièges… (WPF/Silverlight)

imagePromis dans mon dernier billet, le voici enfin ! Ce nouvel article dédié au binding Xaml pèse 77 pages (le record était tenu jusqu’à lors par mon article M-V-VM avec Silverlight avec 70 pages) et se présente sous la forme d’un PDF et de 9 projets exemples.

Le binding cet inconnu … J’en parlais dans mon billet Le retour du spaghetti vengeur, le binding avec sa syntaxe pleine d’accolades et de chaînes de caractères non contrôlées à la compilation est un piège à bugs et la porte ouverte au code spaghetti.

Plutôt que de me lamenter et vous laisser vous embourber dans la sauce de ces spaghetti là, j’ai pris ma plume, et voici le résultat : 77 pages sur le binding Xaml, son fonctionnement, ses différentes syntaxes le tout illustré par des exemples clairs. L’article aborde aussi le débogue du binding assez délicat puisque Xaml échappe au débogueur de Visual Studio, et que le binding n’est que partiellement couvert par Intellisense.

Des conseils, du vécu, beaucoup d’exemples, voilà ce que vous trouverez dans cet article à télécharger en suivant le lien suivant :

Le Binding Xaml – Maîtriser sa syntaxe et éviter ses pièges (WPF/Silverlight)

(Attention, avant de cliquer sur le bouton “télécharger” attendez que la fiche détail de l’article soit bien affichée, sinon le site pensera que vous tentez un accès à une ressource non publique et vous demandera un login… Je reçois tous les jours des demandes d’ouverture de compte provenant de lecteurs trop impatients qui cliquent trop vite sur le bouton ! La prochaine version du site en Silverlight est en préparation et corrigera ce petit problème, mais d’ici là : slow down cowboy !).

Pour vous aider à vous faire une idée du contenu de l’article voici son sommaire :

Sommaire

  • Références    5
  • Code Source    6
  • Préambule    7
  • Le Binding Xaml : Ange ou Démon ?    7
    • Le Binding    8
    • Définition    8
    • Utilisations    9
    • Schéma du principe    9
    • Déclaration    10
      • Par code    10
      • En Xaml    11
  • Les modes de binding    13
    • Le mode OneTime    13
    • Le mode OneWay    13
    • Le mode TwoWay    14
      • Gestion du timing    14
    • Le mode Default    16
    • Le mode OneWayToSource    16
  • Hiérarchie de valeur    18
    • Règles de précédences    19
  • La notion de  DataContext    20
  • Les convertisseurs de valeur    21
    • Définition    21
    • Scénario    21
    • Implémentation    22
    • Utilisation    23
      • Instanciation    23
      • Invocation    23
      • Bonnes pratiques    24
      • Pour résumer    26
  • Les dangers du Binding    27
    • Des chaînes non contrôlées    27
    • Un langage dans le langage    28
  • On fait quoi ?    28
  • Déboguer le Binding    28
    • Vigilance    28
    • Une code Xaml court    29
    • Refactoring sous contrôle    29
    • Utiliser des outils intelligents    29
    • Utiliser Expression Blend    29
    • Vérifier les erreurs de binding dans la fenêtre de sortie    30
    • Créer un fichier des erreurs de Binding    30
    • La feinte du convertisseur inutile    32
    • Quelques outils supplémentaires    33
      • Spy++    33
      • ManagedSpy    33
      • Snoop    34
      • Mole    34
      • Reflector    34
      • Vos neurones    34
  • Les syntaxes du Binding    34
    • Le binding simple    34
      • Binding direct    35
      • Binding sur une propriété    35
      • Binding sur une sous-propriété du contexte    36
      • L’Element Binding    37
      • Convertisseurs de valeur    37
        • Paramètres de conversion    38
      • StringFormat    40
        • Injection de culture    41
        • Le ContentStringFormat    42
        • Gérer les nuls    43
    • Le Binding Multiple    44
      • La classe Personne    44
      • Le code du multi convertisseur    45
      • Le code Xaml    46
    • Le Binding XML    47
      • Binding sur une source Web    47
      • Binding sur une source XML en ressource    48
      • Binding sur une requête Linq To XML    49
    • Le Binding Relatif    52
      • Binding to Self    52
      • Le TemplatedParent Binding    53
      • Le Binding sur recherche d’ancêtre    54
      • Le Binding PreviousData    56
        • La source de données    58
        • La visibilité des flèches : la magie de PreviousData et du Binding Multiple    58
        • Le contenu des textes    61
      • Le Template binding    61
        • Utilité    61
      • Le Collection Binding    67
      • Le Priority Binding    69
  • Les propriétés de tous les bindings    74
  • Conclusion    76

Avril est froid et pluvieux mais les soirées rallongent, c’est le printemps même si cela n’y ressemble pas encore beaucoup, grâce à moi vous savez maintenant comment occuper vos soirées et vos weekend au lieu de faire l’idiot dans les embouteillages des vacances : Lisez cet article !

Et Stay Tuned !

Altair est orphelin

Une triste nouvelle, Edward Roberts, créateur de l’Altair, considéré (à tort *) comme le 1er ordinateur personnel commercialisé (avant l’Apple 1) est décédé. Il avait 68 ans, pas si vieux.

Un certain Bill Gates et son compère Paul Allen avaient pris un accord avec Roberts pour écrire l’Altair Basic et le distribuer avec la machine (montée ou en kit) au sein de la société qu’ils venaient de créer : Microsoft.

PE_Jan_1975_Cover_Mini

La première de couverture de “Popular Electronics”, une revue un peu comme le “Haut Parleur” en France à la même époque, en janvier 1975.

(*) Pour la petite histoire, c’est ce que les américains disent et qui est repris sans vergogne même par un grand quotidien français comme le Monde. C’est oublier que le VRAI 1er micro ordinateur au monde est français, c’est le Micral, développé à la R2E à la demande de l’INRA entre 72 et 73. Son concepteur, André Truong livra le 1er prototype le 15 janvier 1973. Commercialisé ensuite sous le nom de Micral N au prix de 8500 francs (le salaire mensuel d’un cadre à l’époque) il connu un certain succès notamment avec les versions suivantes que la R2E créa, sans changer le nom de Micral. Racheté par la CII Honeywell-Bull, c’est sous le nom de Questar M que les Micral seront commercialisés jusque dans les années 80 par cette dernière.

micral On voit ci-dessus le premier Micral de 73, et on s’aperçoit que l’Altair n’était qu’une copie (première photo).

Ayons ainsi au passage une pensée émue pour André Truong, décédé le 29 mars 2005 à Paris. Avec Roberts ce sont les pères de la micro informatique qui disparaissent définitivement. Une ère, un siècle, un millénaire nous éloigne de cette époque glorieuse des pionniers qui désormais appartient non plus à l’actualité mais aux livres d’histoire, comme la conquête de l’Ouest ou la prise de la Bastille. Ca fiche un coup de vieux, je vous le dit les gars… Mon premier job en informatique ça a été sur le Questar M dans les années 80, à la CII HB. Alors en ce jour pluvieux et froid, la mort de Roberts fait résonner en échos de vieux souvenirs, un brin de nostalgie.

Mais n’ayez crainte, ce n’est pas un coup de blues, et je vous prépare pour ce week-end un article géant de 71 pages sur le Binding Xaml qui va vous secouer les neurones !

"Alors rangez vos kleenex bande de mauviettes* et Stay Tuned ! (Sir! Yes Sir !)"

(à prononcer comme un militaire gradé s’adressant à ses troupes dans un film de guerre américain :-) )