#AKWP8 / Hackathon Windows Phone 8 au Moulin de la Forge

16. December 2012 00:12 by Renaud in   //  Tags:   //   Comments (0)
Après 3h de route, on arrive enfin au Moulin de la Forge, un endroit un peu coupé du monde (et du réseau Internet :)) et qui, pour la deuxième fois, est squatté par la communauté des développeurs Windows Phone. Le #AKWP8, ce n'est pas un "concours" pour les développeurs. Il n'y a pas de pression, pas d'engagement. C'est simplement un weekend, organisé par Microsoft France, pour réunir tous les passionnés. Alors forcément ça attire du monde. Pas moins de 100 développeurs dans la salle. On a attendu que tout le monde arrive et s'approprie un bonnet pour faire le lancement. Le programme est complètement libre : chacun bosse sur ce qu'il veut, seul ou en équipe. Mais le weekend est rythmé par quelques milestones:

Vendredi soir de 23h à ... Bootcamps :

Les évangélistes Microsoft et quelques volontaires organisent des petits ateliers pour parler de technologies à la demande des participants. On a eu droit à  DirectX, le NFC sur Windows Phone, Windows Azure Mobile Services, Windows 8 et le Modern UI, etc...

Samedi, 12h-18h, Fast Code !

Pierre Cauchois lance le sujet à midi : développer une app sur le thème du #AKWP8 ou du Moulin de la Forge ! Ceux qui le veulent ont 6h pour développer un proto pour en faire une démo. Juste pour le fun :)

Samedi de 20h à 2h matin, Bootcamps II

Pour ceux que ça intéresse, petits cours sur le portage d'application Windows Phone vers Windows 8, et WP7 vers WP8.

Dimanche de 11h jusqu'au départ... Submission party

Parce qu'au final on espère voir quelques apps soumises sur le store :)

Les achievements

Mais le top du top, c'est cette idée d'achievements pour faire gagner des stickers aux devs qui réussiront quelques défis! Rien de très sérieux, mais ça fait toujours plaisir :) Mon laptop devient mon tableau de chasse ! Quelques-uns des achievementsque j'ai débloqué :
  • FastCoder : pour avoir participé au FastCode ^^
  • Samaritan : pour avoir aidé quelques personnes qui peuvent en témoigner.
  • Azure : une app avec un backend dans le cloud !
  • ....

C'est la deuxième fois que j'ai la chance de participer à cet événement qui est juste épique et j'ai déjà hâte de voir ce que Microsoft nous proposera pour la prochaine édition :) Si vous voulez suivre un peu l'event en live, c'est ici : #AKWP8 !

Retour sur le Windows App Day 2012

25. November 2012 14:11 by Renaud in   //  Tags:   //   Comments (0)
Petit retour sur le Windows App Day, cette journée organisée par Microsoft et destinées aux développeurs et graphistes initiés ou non. En effet, il s'agissait d'une série de sessions de 1h chacune, réparties sur deux tracks : Developer et UX & Designer. Pour l'ouverture, nous avons pu voir tour à tour Luc Van de Velde (Director Developer & Platform group) et Katrien De Graeve, David Hernie et Nick Trogh (tous trois Technical Evangelist) parler de la direction prise par Microsoft en nous présentant quelques success stories et témoignages de développeurs. Le ton est donné : on va parler Windows 8, Windows Phone 8 et Windows Azure ! :) Mais juste après un petit break...

Pour les sessions suivantes, l'audience se sépare en deux. On a eu droit à quelques sessions intéressantes dont je vais vous faire le résumé. Je n'ai suivi que la partie Developer, donc je ne pourrai malheureusement pas parler du reste. Mais d'après les quelques échos que j'ai eu sur le moment, les sessions UX & Design valaient vraiment la peine d'être vues ! Windows Phone 8 Development by Maarten Struys

> Lire l'article Windows Phone 8 Development

Windows Azure Mobile Services, Connecting Cross Platform Devices by Kristof Rennen

> Lire l'article Windows Azure Mobile Services : intro

From Slider to Gauge: building WinRT custom controls by Diederik Krols

Cette session montrait différentes manières de créer un contrôle custom, soit à partir d'un contrôle existant, soit from scratch.

What it takes to make Mine for Facebook : learn and apply to your next Windows Store app by Kevin Dockx

Cette dernière partie était une série de conseils du développeur de l'application Mine for Facebook (que vous devriez d'ailleurs essayer ;) ). C'était un excellent retour d'expérience pour terminer cette journée. Kevin nous suggérait entre autres de trouver un ami graphiste ("on ne laisse pas les graphistes développer, et on ne devrait sans doute pas laisser les développeurs faire du design"). Il nous a ainsi montré l'évolution de son application, depuis son premier essai jusqu'au rendu final, en expliquant les apports du graphiste au projet.

Il est ensuite rentré dans des conseils plus techniques, comme par exemple :

  • N'utiliser que des librairies tierces qui ont fait leurs preuves. Vous n'avez pas envie de voir votre projet "cassé" à cause d'une librairie qui n'est plus mise à jour.
  • Lorsque l'on travaille en asynchrone, penser à annuler les tâches toujours en cours mais plus nécessaires grâce à des CancellationToken.
  • Consumer/Producer pattern et BlockingCollection pour pré-fetcher des données et apporter une meilleure expérience utilisateur. La perception est plus forte que la réalité.  Et peu importe combien votre application est performante, ce qui compte c'est l'impression finale qu'aura l'utilisateur !
  • Utiliser un outil d'analytics pour loguer les erreurs mais aussi analyser le comportement des utilisateurs. Suggestion : MarkedUp.
En résumé, la journée a été bonne et enrichissante. À refaire sans hésiter :)

Un été pour développer une app Windows 8 !

5. July 2012 22:07 by Renaud in   //  Tags:   //   Comments (0)

Portail Windows 8

Si vous ne l'avez pas encore remarqué, le portail Windows 8 - comme la majorité des sites Microsoft - a fait peau neuve : http://www.microsoft.com/belux/msdn/metromap/ Ce site est le point d'entrée pour les développeurs qui souhaitent se lancer sur la nouvelle plateforme Windows 8. A vrai dire, le moment est plutôt bien choisi pour s'y mettre. Microsoft propose un tas d'opportunités durant l'été pour que vous puissiez être parmi les premiers à publier vos applications dans le Store, dès la sortie de Windows 8. Si l'aventure vous intéresse, commencez par suivre le lien ci-dessous et lisez la suite pour savoir pourquoi vous devriez vous lancer, et comment on peut vous aider :

Build your app NOW !

4 étapes pour Windows 8

 Microsoft vous propose de publier votre application en seulement 4 étapes :
  • Téléchargez les tools : tout est gratuit ! Vous pouvez tester la Release Preview de Windows 8, ainsi que Visual Studio 11 Ultimate, oui oui ! :)
  • Formez-vous : il y a déjà énormément de ressources en ligne, et vous trouverez ce qu'il vous faut en fonction du temps que vous avez à y consacrer. Par exemple :
  • Participez à un App Clinic : en avançant dans le développement de votre application vous pourriez avoir besoin de conseils UX, ou faire face à des problèmes plus complexes. Les App Clinics sont là pour ça ! Vous pourrez rencontrer des experts qui vous permettront de tester vos apps sur une large gamme d'appareils, vous donneront des conseils sur l'expérience utilisateur de votre application, les guidelines Metro, et feront en sorte que votre application soit au top pour entrer dans le Store !
  • Terminez avec un App Excellence Lab : une fois passé par l'App Clinic, et lorsque vous vous sentirez prêt, vous pourrez présenter votre app pour un Excellence Lab. Il s'agit d'un rendez-vous de 2 heures avec un expert de chez Microsoft qui vérifiera que votre application remplit toutes les exigences qualitatives. Si c'est le cas, vous recevrez alors un Windows Store Token qui vous permettra de publier votre application sur le Store de Windows 8 !
Le MIC vous propose également une raison supplémentaire : un appel à projets lancé récemment en partenariat avec AGC. Vous pouvez retrouver toutes les infos nécessaires dans cet article : Call for projects : Smart Mirror Device W8 applications. Si vous ne voulez pas vous lancer seul dans l'aventure, sachez que plusieurs évènements qui peuvent vous intéresser sont organisés durant l'été :
  • Le 10 juillet prochain aura lieu le Windows 8 Summer Camp au MIC Belgique. Il s'agit d'une journée de formation donnée par Loïc Bar, spécialiste des technologies Microsoft dont Silverlight, ASP.NET MVC, WCF, ... L'inscription est gratuite et peut se faire ici : http://events.mic-belgique.be/event/windows-8-camp
  • Ne manquez pas non plus le premier Summer App-a-thon Windows 8 ce 12 juillet. Il se tiendra à la côte, et plus précisément au Casino de Blankenberge ! Suivez ce lien pour vous inscrire ou avoir plus d'infos : Coding on the beach !
  • Si vous n'êtes pas trop plage, ou que vous êtes en vacances durant le mois de juillet, vous pouvez toujours vous rattraper le 8 août avec le deuxième App-a-thon qui aura lieu cette fois à Anvers : the Metro-politan App-a-thon !
Le MIC sera présent à chacun de ces évènements, donc n'hésitez pas à vous inscrire car vous ne serez pas seul ! Et si vous n'avez aucune idée de ce que peut-être un app-a-thon (ou hackathon), regardez plutôt l'article précédent : Un weekend au BeMyApp. Le MIC était de la partie, et l'ambiance était juste énorme ! Dans tous les cas, si l'idée de développer une application vous tente, n'hésitez pas à nous contacter par mail, sur la page Facebook du MIC, ou via notre compte Twitter... Nous serons ravis d'avancer avec vous !

Ça code partout en Belgique : les dates à ne pas manquer !

1. June 2012 13:06 by Renaud in   //  Tags:   //   Comments (0)

Si certains pensent encore qu'il ne se passe pas grand chose en Belgique, les voilà servis ! ^^

Cet été, il y a déjà au moins quatre événements majeurs à ne pas manquer ! Dans l'ordre, on retrouve:

  • Le Microsoft Community Day 2012, le 21 juin : l'événement qui regroupe toutes les communautés et users groups de Belgique ! Une journée gratuite pour apprendre plein de trucs cools: http://www.communityday.be/. Attention d'après un tweet récent (3 juin), il ne reste que 50 places ! Donc courrez vous inscrire ;)
  • BeMyApp, du 29 juin au 1 juillet : 48h de pour coder une killer app sur l'environnement de son choix (Windows Phone, iOS, Android, web) et défendre la Belgique dans une compétition mondiale !  Toutes les infos sont disponibles ici: http://be.bemyapp.com/. Ca ne s'adresse pas uniquement aux développeurs, mais aussi aux porteurs d'idées, aux designers, et aux supers touristes ! :D L'entrée est gratuite pour tout le monde. Donc sauf cas de force majeure, il n'y a pas vraiment à hésiter!
  • Windows 8 Summer App-a-thon, le 12 juillet : Coding on the beach, parce que c'est pas vrai qu'on a peur du soleil ! Une journée de dev à la mer du nord sous le soleil de Belgique. Faudra penser à apporter de quoi bien s'hydrater (ce n'est pas @svidouse qui me contredira !). La location exacte n'est pas encore annoncée, mais vous pouvez rester au courant en vous inscrivant déjà sur facebook: https://www.facebook.com/events/316680961739310
  • Windows 8 Summer App-a-thon , le 8 août : pour ceux qui n'auront pas eu la chance de participer à la première édition, ou ceux qui sont très motivés, voici la version Metropolitaine qui aura lieu du côté d'Anvers, dans un endroit encore tenu secret ! Vous pouvez suivre les nouvelles à propos de cet event ici: https://www.facebook.com/events/283129108449164/

Enfin, notez aussi ces quelques dates :

Sessions gratuites d'introduction au SDK Kinect 1.5  :

6 juin : @micbelgique, sur Mons : http://events.mic-belgique.be/event/kinect-sdk-hands-on--3 13 juin : @MICBrussels : http://micbru.fikket.com/event/kinect-sdk-hands-on--5 3 juillet : @MICBrussels : http://micbru.fikket.com/event/kinect-sdk-hands-on--6

Visionnage en live de la session #MeetAzure présentée par Scott Guthrie :

7 juin : @micbelgique, sur Mons : http://mic.fikket.com/event/meet-windows-azure-live


Il y a certainement encore beaucoup de choses à venir ! N'hésitez pas à me suivre sur twitter (@DumontRenaud) pour être tenus au courant !

Vous pouvez également suivre @DavidHernie et @micbelgique pour être les premiers informés ! ;)


Update 14/06 : Les inscriptions pour le Summer App-a-thon à la côté belge sont ouvertes !

Pourquoi vous devriez contribuer à StackOverflow?

3. February 2012 01:02 by Renaud in   //  Tags:   //   Comments (4)

Faut-il encore vraiment présenter StackOverflow?

StackOverflow, la bible des développeurs

Toute personne ayant un jour cherché sur internet la solution à une question de développement pour  une raison diverse a forcément dû atterrir sur ce site à l'apparence douteuse! (incompréhension d'un langage oublié de tous; sombre histoire d'erreur, identifiée par un code numérique n'étant référencé dans aucune documentation; comportement estimé anormal d'un bout de code; devoir pratique à rendre pour le lendemain;  et j'en passe et des bien plus bonnes !)

Si vous êtes allergiques à l'anglais, vous allez peut-être passer directement votre chemin, mais alors shame on you! Vous n'imaginez pas ce que vous ratez.

Effectivement, StackOverflow, c'est une énorme référence! C'est le wikipedia du développeur! Ca fonctionne sur le même principe: le site, un amas de questions, est autogéré par la communauté qui répond, corrige, débat, et vote pour les meilleures questions et réponses.

Le résultat est énorme: un endroit centralisant des réponses souvent très intéressantes, détaillées et argumentées. Les propositions de réponses jugées mauvaises ou inutiles sont downvotées, et se retrouvent en bas de page histoire de ne pas gêner. Mais tout ça est régulé très sainement, puisque les droits des utilisateurs sur le site sont proportionnels à leur contribution. Ainsi, n'importe qui ne peut pas se permettre de dégrader les lieux au premier passage.

StackOverflow, à l'écoute des développeurs

Soyons honnête, il se peut que vous n'y trouviez pas la solution à tous vos problèmes, malgré ce que je viens de dire... A ce moment-là, peut-être qu'il serait temps de vous décider à poser vous-même votre propre question. C'est le premier pas de la contribution. En effet: demander, c'est déjà contribuer. N'hésitez pas alors à fournir du code, des détails, et ce que vous avez déjà tenté, si cela peut aider les autres à identifier ce qui coince!

Peut-être que votre question trouvera rapidement acquéreur, et vous pourrez alors récompenser celui qui vous aura aidé. Dans le cas contraire, gardez patience. Vous avez jeté un premier pavé dans la marre, et même si personne n'a directement de solution, vous constaterez que les autres développeurs sont souvent généreux en conseils et tenteront de la découvrir avec vous. De plus, vous serez à l'origine d'un post qui pourra peut-être permettre à des collègues faisant face au même problème de se rassembler pour apporter de nouvelles informations, ce qui aidera d'autant plus à trouver une solution. Dans tous les cas, les informations récoltées serviront plus tard à d'autres personnes, parce que vous aurez pris la peine de poser publiquement une question !

StackOverflow, valorise les développeurs

Une chose qui me plaît énormément dans la vie, et qui se dénote particulièrement bien dans le monde de la programmation, c'est que chacun peut être un expert à son propre niveau. J'entends par là qu'on a tous notre propre expérience, et qu'il est toujours possible, et agréable, d'en faire profiter quelqu'un d'autre. Il y a de nombreuses façons d'exprimer et de partager ses propres connaissances: à l'oral, en privé ou en public, lors d'une brain session, d'une formation, d'un live-meeting, de manière écrite, dans un blog, une revue, un bouquin, ... Et pourquoi ne pas faire ça comme un jeu, en contribuant à l'une des plus grandes communautés de développeurs?

J'ai mis un certain temps avant de répondre à ma première question sur StackOverflow. Au départ, j'avais toujours l'impression que les questions étaient trop compliquées pour moi. Ensuite, je suis tombé sur un sujet que je connaissais, pour avoir déjà rencontré le problème. J'y ai répondu maladroitement. Ma réponse n'a pas été acceptée par l'auteur de la question, mais un utilisateur a voté positivement pour dire qu'elle était du moins utile. Quelques jours plus tard, je remets le couvert avec deux nouvelles réponses (dont une qui parlait de Java :) j'ai encore de bons restes malgré tout! ), et là c'est la consécration! Les deux réponses sont acceptées par les auteurs, et je gagne 50 points de réputation!

C'est à moment-là que j'ai découvert l'autre côté de StackOverflow. Le côté le plus passionnant. Quand je réponds à des questions, par principe, je vérifie ce que je crois être juste avant de le poster. Et croyez-le ou pas, mais ça me fait apprendre énormément de choses ! Soit parce que je me rends compte de mes erreurs, soit parce que je comprends plus en profondeur le fonctionnement de l'un ou l'autre concept! Et pour finir, d'autres me récompensent d'un upvote. Pour moi, c'est extrêmement valorisant.

Je pense sincèrement que chaque développeur, ayant envie d'apprendre et de partager, peut prendre conscience, grâce à StackOverflow, du potentiel qu'il représente, et y trouver une source de satisfaction, et de confiance en soi.

De consommateur à acteur

Il ne tient qu'à vous maintenant, si ce n'est pas déjà fait, de changer de statut et de devenir créateur de contenu plutôt que consommateur. Vous êtes déjà un expert, à votre échelle. Faites-en profiter les autres. La création incite à la création.

Si vous êtes motivés, sachez que StackOverflow n'est pas le seul site du genre, vous pourrez en trouver d'autres susceptibles de vous intéresser sur StackExchange.

En espérant avoir suscité l'une ou l'autre vocation !

( Ps: prévenez-moi si vous dépassez un jour le score de Jon Skeet )

[WP7] [MVVM] Construire une application étape par étape : 1/ Introduction

11. January 2012 09:01 by Renaud in   //  Tags:   //   Comments (5)

Cet article fait partie d'une longue série dont le but est de montrer comment réaliser une application pour Windows Phone de A à Z en évitant de tomber dans les pièges les plus courants. Pour cela, je vais réaliser une application à partir de zéro et décrire les différentes étapes sur ce blog. L'application en question sera finalement publiée sur le marketplace une fois terminée. Cette application utilisera le pattern MVVM, qui va nous aider à solutionner les difficultés techniques que nous pourrions rencontrer. Elle fera appel à un webservice, mis à disposition au travers de l'API Last.FM.

Le plan:

Le développement sera constitué de trois grandes parties, parfois subdivisées en tâches pour raccourcir les articles:

  1. Introduction
  2. Modèle:
  3. ViewModel
    • Les vues théoriques
    • Assemblage de ViewModels
    • Actions et commandes
    • Communication entre les ViewModels (Messenger)
  4. View
    • Binding
    • Templates
    • Application localisée

 Quel est le but de l'app réalisée?

MyShows (ce sera le nom de cette application) va utiliser les services de Last.FM pour fournir une liste de concerts à proximité de l'endroit où se trouve l'utilisateur, ainsi que la possibilité de consulter les concerts des artistes qu'il souhaite. On pourra donc afficher une timeline des concerts des artistes suivis, et proposer des artists similaires que l'utilisateur pourrait vouloir suivre également.

Voilà donc très brièvement la description fonctionnelle de ce que l'on va réaliser dans les articles qui suivent.

Avants-propos

Depuis un an maintenant que je développe des applications pour Windows Phone 7, j'ai rencontré bon nombres de situations à s'arracher les cheveux. Des dépendances cycliques, des problèmes de binding, des difficultés aves les requêtes asynchrones, ...

Cela était dû en grande partie à ma mauvaise connaissance de Silverlight. En fait, j'ai vraiment découvert Silverlight au moment de commencer le développement pour Windows Phone.

Avant ça, ma seule expérience .NET consistait en un projet ASP.NET MVC2, et quelques webforms. Je n'avais donc jamais entendu parler du Binding, et j'ai découvert sa magie petit à petit au cours des différents projets qui suivirent.

La raison pour laquelle j'ai décidé de faire cette série d'articles est qu'il m'est souvent arrivé récemment d'être questionné par d'autres développeurs sur "comment je pourrais faire ceci ou cela?", comme par exemple "comment retrouver le libellé de mon produit lorsque je clique sur le bouton supprimer de ce produit?". Et là, je me demande toujours comment ont-ils fait pour arriver à avoir ce genre de besoins?

Alors il y a deux réponses possibles: Soit on passe du temps à expliquer qu'il y a manifestement un problème de design dans l'application. Il faut alors, en essayant de trouver les mots justes pour ne pas faire de peine au développeur, lui conseiller de refactorer son application vite fait avant que cela ne se complique davantage. Soit on trouve un workaround mais il faut à ce moment-là garder à l'esprit que ce n'est pas quelque chose à refaire. En effet, ce n'est pas parce qu'une solution semble simple qu'il faut en user jusqu'à la corde. Et inversement, la complexité n'est pas une preuve de qualité. Je sais bien qu'on est plutôt fainéants, nous, développeurs, mais il faut savoir trouver le juste milieu entre le trop et le trop peu.

Donc dans le cas d'un petit projet, ou d'un POC, ce ne sera pas nécessaire de déployer l'artillerie lourde.

Le problème est que si l'on souhaite continuer à faire évoluer l'application, on risque à un moment ou à un autre de se retrouver fasse à une impasse. Et il sera un peu tard pour se remettre en question... Alors pour ceux qui souhaitent un projet pérenne, il vaut sans doute mieux prendre le temps de s'arrêter et de se poser les bonnes questions maintenant, pour ne pas le regretter après!

C'est pour pouvoir toucher un maximum de personnes que j'ai commencé ce nouveau projet. J'espère ainsi qu'il permettra à quelques uns d'entre vous de trouver des solutions aux problèmes auxquels vous faites face, ou bien qu'ils vous éclaireront sur un sujet peut-être encore un peu flou!

Introduction

Un peu de théorie (très rapidement :) )...

Le pattern MVVM signifie Model - View - ViewModel. Il est principalement utilisé dans les applications de type WPF, Silverlight. Si vous vous êtes déjà un peu plongé dans le développement Windows Phone, il est pratiquement impossible que vous n'en ayez jamais entendu parler ! :)

L'idée de ce pattern, est de fournir un ensemble de principes pour architecturer votre application avantageusement. Les principaux bénéfices que vous en tirerez sont:

  • Réutilisation du code
  • Dépendances faibles
  • Possibilité de travailler sur le Modèle, les Views, ou les ViewModels de manière séparée ou simultanée (facilite le travail en équipe)
  • Séparation claire des rôles. Ainsi, une personne travaillant sur les Views n'aura pas à écrire de code proprement dit. Vous pourrez donc confier ce travail à un designer.
  • Utilisation des bienfaits du Binding et des DataTemplates
  • et probablement d'autres que j'ai oublié pour le moment...

Les rôles

Voici une définition rapide des composantes du MVVM:

Model: le modèle ne correspond pas uniquement au modèle au sens propre, c'est-à-dire la représentation des données. Il sera aussi constitué des services permettant d'accéder à ces données ou de les stocker, par exemple une couche utilisant le pattern Repository (on y reviendra par la suite).

View: la vue est un point essentiel du projet, puisque c'est elle qui sera exposée à l'utilisateur. Ici, ce sont les pages XAML, qui seront chargées d'afficher les données du modèle, des informations sur l'état de ces données et de mettre à la disposition de l'utilisateur des moyen d'interagir avec ces données.  Malheureusement pour moi je n'ai aucun talent dans ce domaine, mais je ferai de mon mieux pour vous épater!

ViewModel: last but not least, le viewmodel va jouer un rôle important puisqu'il va permettre non seulement de faire appel aux services du modèle pour charger les données, mais également de décider de la manière dont les données seront exposées. Le ViewModel va ainsi lister les données qui seront affichées à l'écran, mais pas la façon de les afficher (ceci étant du domaine de la View). D'autre part, il va également se charger d'effectuer des actions et de manipuler le modèle, parfois en faisant appel à la couche service de celui-ci.

Dépendances faibles

On peut dès à présent constater la notion de dépendance faible:

Le modèle ne connait pas le ViewModel, ni les Views. Les couches de services du modèles, peuvent être exposées sous forme d'interfaces.

Le ViewModel, ne connait pas les views. Il connaîtra le modèle client proprement dit (les classes représentant les données), mais ne fera appels aux services que sur base des interfaces. Ceci laisse donc libre choix dans l'implémentation de ces services, et permettra également d'utiliser de faux services retournant des données valides pour faire des tests.

La View se servira du Binding pour utiliser les propriétés exposées par le viewmodel. Encore une fois, vous verrez ici qu'il n'y a pas de dépendance forte, car la vue ne connaît pas le type du ViewModel. La résolution ne se fera qu'au moment de l'exécution de l'application.

Let's get started

Rien ne vaut un peu de pratique pour que toutes les pièces s'assemblent alors commençons tout de suite.

Pour bien commencer, je vous suggère de créer un nouveau projet et d'y ajouter les références au MVVM Light Toolkit en utilisant NuGet. Ce framework (il en existe d'autres mais c'est celui que j'utilise régulièrement et que j'utiliserai dans les articles qui suivront) contient un ensemble d'outils qui nous permettront de mettre en place facilement une architecture MVVM!

[caption id="attachment_1082" align="aligncenter" width="765" caption="Nouveau projet Panorama avec MVVM Light Toolkit"][/caption]

Les articles suivant seront publiés régulièrement, donc n'hésitez pas à revenir de temps en temps pour voir s'il y a du nouveau. Ou suivez-moi sur Twitter pour être tenus au courant! @DumontRenaud

[CRM 2011] Débugguer un plugin dans CRM 2011 avec Visual Studio 2010

26. September 2011 09:09 by Renaud in   //  Tags:   //   Comments (0)

À ce stade, vous avez certainement déjà déployé votre premier plugin. J'espère que pour vous que tout s'est bien déroulé du premier coups. Mais dans ce comme dans l'autre, il peut être très intéressant de pouvoir débugguer votre plugin.

Pré-requis: Pour ce qui va suivre, il est nécessaire d'avoir Visual Studio installé sur le serveur sur lequel se trouve l'installation de CRM. Je n'ai pas encore utilisé le remote debugging, mais ça ne saurait tarder, et je vous ferai alors un autre article à ce sujet ;)

Vous pourrez ainsi faire des tests, explorer les données dont vous disposez, et apprendre à mieux utiliser les plugins.

Pour débugguer, rien de très compliqué: rappelez-vous l'enregistrement de votre assembly dans CRM.  Aviez-vous fait attention aux remarques concernant les fichiers .pdb? Ces grâce à eux que vous pourrez suivre l'exécution de vos plugins dans Visual Studio.

Commencez par placer le fichier .pdb correspondant à votre assembly dans le dossier server/bin/assembly. Attention de bien copier la bonne version du fichier, sinon le debug ne fonctionnera pas. C'est pour cela que la solution du stockage sur disque de votre assembly est pratique en développement. Vous pouvez, après chaque nouveau build de votre assembly, remplacer les deux fichiers (.dll et .pdb) en une seule opération, ce qui évitera toute erreur.

Ensuite, dans Visual Studio, allez dans le menu Debug et choisissez Attach to Process...

Dans la liste des processus actifs, cherchez w3wp.exe. S'il n'apparaît pas, c'est peut qu'il faut cocher la case "Show processes in all sessions". [caption id="attachment_554" align="aligncenter" width="738" caption="Dans mon cas, le process qui m'intéresse est celui lié à l'utilisateur "crm""][/caption]

Il se peut aussi que vous ayez plusieurs fois ce processus dans la liste. Si vous n'êtes pas sûr de quel processus vous intéresse réellement, ouvrez une page web pour vous connecter à votre organisation CRM. Ouvrez également le Task Manager pour observer les process w3wp.exe. Rafraîchissez la page affichée dans Internet Explorer, et vous verrez l'un des process consommer d'avantage de ressources pendant un bref instant. C'est lui le coupable :) Retenez le PID un cours instant, le temps de le retrouver dans Visual Studio!

Cliquez ensuite sur "Attach". Vous serez prévenu que cela peut endommage votre système, mais pas de panique, on ne fait rien de mal.  Confirmez!

Il ne reste plus maintenant qu'à mettre un point d'arrêt quelque part dans votre code, vous rendre sur la page concernée par votre plugin, et si tout à été fait correctement, l'exécution s'interrompra comme prévu! :)

[caption id="attachment_702" align="aligncenter" width="449" caption="Image thématique :)"][/caption]

Attention, lorsque vous voudrez remplacer l'assembly et le pdb par un nouveau build sur votre serveur, il se peut que les fichiers soient en cours d'utilisation et donc inaccessibles. Il suffit de tuer le process de crm utilisé précédemment via le Task manager, le temps de remplacer les fichiers. Ensuite, rafraîchissez la page dans CRM pour créer un nouveau process avec un nouveau PID auquel vous pourrez de nouveau attacher Visual Studio!

Bon débug ;)

Le b.a.-ba du debug avec Visual Studio.

16. September 2011 09:09 by Renaud in   //  Tags:   //   Comments (5)

On a reçu pas mal de commentaires et de questions via le formulaire de contact sur le blog WP7Team, et en y répondant je me suis rendu compte que beaucoup de développeurs débutants se retrouvent coincés face à des problèmes simplement parce qu'ils ne savent pas débugger. Cet article est une adaptation d'un des mails que j'ai écrit pour répondre à l'une des questions reçues.

Coder sans débugger, c'est un peu comme avancer dans un labyrinthe les yeux bandés! Dès que vous vous retrouvez face à un mur, vous êtes incapable de dire comment vous êtes arrivés là.

Sans être un expert en la matière, je pense pouvoir vous donner quelques conseils très très basiques qui pourront peut-être vous éviter des crises de nerfs!

1/ Lancer l'appli en Debug.

Premièrement, passez en mode Debug. Pour lancer l'exécution de votre application en Debug, cliquez sur la flèche verte ou appuyez sur F5 (Start Debugging).

[caption id="attachment_241" align="aligncenter" width="265" caption="Configuration: Debug"]Debug[/caption]

2/ Placer des breakpoints.

[caption id="attachment_243" align="aligncenter" width="750" caption="Breakpoints: points d'arrêt"]breakpoint[/caption]

Dans la barre de gauche il y a des points rouges. Ce sont des points d’arrêts, et quand je lance mon appli en mode debug, comme c’est le cas ici, l’exécution s’arrêtera à chaque point d’arrêt !

Donc, lancez l’application, et vous verrez le premier point d'arrêt rencontré se surligner en jaune :

[caption id="attachment_563" align="aligncenter" width="1030" caption="La ligne surlignée en jaune est celle sur le point d'être exécutée!"][/caption]

Notez bien que la ligne surlignée n'a pas encore été exécutée!

Si vous vous arrêtez sur la ligne suivante, myObject ne sera pas encore initialisé et aura null pour valeur.

MyObject myObject = new MyObject();

3/ Naviguer en debug

Le bouton « play »  (F5) permet de relancer l’exécution jusqu’à ce qu’on rencontre un nouveau point d’arrêt. Vous pouvez stopper ou redémarrer l'application: 

Pas loin, vous trouverez des contrôles assez intéressants: 

Le premier, StepInto (F11), va passer à la ligne suivante où rentrer à l’intérieur d’une méthode si la ligne sur laquelle on se trouve fait appel à une méthode !

Celui du milieu, StepOver (F10), va passer à la ligne suivante, sans s'occuper des appels de méthodes.

Et le dernier, StepOut (Maj + F11), va relancer l’exécution jusqu’à ce qu’on remonte d'un niveau, c'est à dire jusqu'à ce que l'on sortant de la méthode dans laquelle on se trouve pour arriver au code ayant fait appel à cette méthode.

4/ Observer

Un des avantages des points d'arrêts est qu'ils vous permettent à un moment donné d'observer la valeur des variables que vous avez créées. Cela vous aidera peut-être à comprendre pourquoi votre programme ne se comporte pas comme vous l'espériez!

Il existe plus moyens pour observer vos variables, comme cette vue, que vous devriez apercevoir lorsque vous lancez votre application en debug:

Si cette vue n’est pas affichée chez vous, allez dans le menu Debug > Windows.

Affichez « Locals » et dans « Watch » affichez « Watch1 » (On parlera de celle-ci plus bas ;) ).

Une autre possibilité pour espionner vos variables consiste simplement à placer le curseur de votre souris par dessus un nom de variable.

Sur l'image ci-dessus, en passant par-dessus le« e », vous pouvez voir grâce au menu contextuel que cette variable représente un DownloadStringCompletedEventArgs. Même pas besoin de connaître le début du code! Si l'on avait placé le curseur par dessus le "Cancelled", vous pourriez voir apparaître [ e.Cancelled |false ] (ou true évidemment :) c'est selon! )

Regardons un exemple un peu plus complexe, tiré d'un code de MSDN:

Ici, l'objet this est un objet de type MainForm de l'espace de nom PluginRegistrationTool. Les valeurs affichées juste en dessous représentent les valeurs des propriétés , et les champs private de l'objet.

La première ligne, "base", permet d'accéder aux propriétés et champs hérités de la super-classe qui est ici System.Windows.Forms.Form.  On peut décider d'aller voir ce qu'il s'y cache:

On peut voir que cette classe hérite elle-même de System.Windows.Forms.ContainerControl, qui possède une quantité de propriétés. Vous pouvez bien évidemment décortiquer chacune de ces propriétés exactement de la même manière :)

5/ Evaluer des expressions

Explorer à la souris, c'est pratique et rapide, mais parfois ce ne sera pas suffisant. C'est le cas dans l'exemple suivant:

J'aimerais beaucoup savoir ce que vaut Math.Pow(z, y) à ce moment du programme, parce que ça m'aiderait à comprendre pourquoi je n'ai pas de chance et ne satisfait jamais la condition! Mais je suis nul en math :/ Et en fait, j'aimerais aussi savoir combien vaut mon opération si vraiment ce n'est pas égal à 100! :)

C'est là qu'intervient la vue Watch que je vous ai fait ajouter tout à l'heure!

Pour l'utiliser, rien de très compliqué, il suffit de sélectionner une expression, et de la glisser sur la vue :) On sait maintenant que le résultat est...

Et puis rien ne nous empêche de mettre le premier membre de l'expression tout entier!

[caption id="attachment_579" align="aligncenter" width="472" caption="Effectivement, on est loin du compte..."][/caption]

Et ce qui est tout aussi pratique, c'est que vous pouvez finalement taper n'importe quelle expression directement dans la colonne Name de la vue Watch:

5/ Les exceptions

Pour terminer, parlons d'un des points essentiels: les exceptions! Je vais reprendre le problème rencontré par le développeur qui nous avons contacté et qui a fait que j'écris ce post aujourd'hui.

Cette personne développait une application pour Windows Phone et utilisait un HyperlinkButton, avec pour valeur de la proprité NavigateUri un lien vers une page web. Dans son dernier mail, cette personne me disait:

[...] je suis incapable de comprendre pourquoi lorsque je clique sur le titre du post, sur lequel j'ai fait pointer l'url de la vidéo désormais, fait planter l'application, au lieu d'ouvrir IE [...]

Là, j'ai compris que je ne pouvais pas le laisser continuer à développer sans lui apprendre à lire et comprendre les exceptions.

Je ne vais pas faire ici un cours complet sur ce qu'est une exception. Le but n'est pas que vous sachiez comment créer les vôtres, mais bien de comprendre ce qu'elles veulent dire. Sachez déjà que lorsqu'une exception est lancée dans votre application, cela signifie que quelque chose ne s'est pas passé comme prévu, et cela empêche votre programme de continuer à s'exécuter! En général, chez un débutant, cela signifie tout simplement le plantage et la fermeture de l'application illico!

Si toutefois vous ne savez pas comment gérer ses exceptions, je vous invite grandement à lire ceci: try-catch (C#).

Revenons au problème:

J'ai mon HyperlinkButton, et sa propriété NavigateUri pointe vers une url tout à fait correcte. Lorsque je lance l'application en debug, et que je clique sur le lien, il y a effectivement une erreur, et je me retrouve dans cette partie du code :

 

Ici, l’exception est traitée par le code généré par visual studio quand vous créez un projet (c'est un peu un cas particulier) mais en général quand il y a une exception, l’application s’arrête et un pop-up apparaît dans visual studio en pointant sur la ligne de code qui a déclenché l’exception !

[caption id="attachment_584" align="aligncenter" width="731" caption="NullReferenceException signifie que vous essayez d'appeler une méthode sur une référence null. Généralement, le type de l'exception est assez explicite pour comprendre quel est le problème."][/caption]

Dans le cas du problème de navigation, ce n'est à première vue pas aussi simple. Mais les techniques apprises plus haut vont vous permettre de vous en sortir sans difficulté!

Si vous exploriez le paramètre « e », vous verriez dans e.Exception.Message la valeur : {"Navigation is only supported to relative URIs that are fragments, or begin with '/', or which contain ';component/'.rnParameter name: uri"}.

On comprends donc bien que l’HyperlinkButton ne permet tout simplement pas de naviguer vers une page web mais uniquement vers des pages de l'application même.

Matthieu Vandenhende apporte une petite correction dans les commentaires! N'hésitez pas à visiter son blog. C'est plein de bons conseils sur le développement Windows Phone!
 Il est tout à fait possible de naviguer vers une page web depuis un HyperLinkButton. La solution est de préciser comment va s’ouvrir la page avec l'attribut TargetName. Ex:
<HyperlinkButton Content="Devillu BLOG"
                 NavigateUri="http://blog.devillu.com" TargetName="_blank" />

Voilà, donc, comment Visual Studio peut vous permettre de mieux comprendre les problèmes rencontrés, et vous aider à vous corriger :)

La solution, en bonus! (pour ceux que ça intéresse :) )

Pour naviguer vers une page web sur Windows Phone 7, il faut utiliser l'un des nombreux launchers disponibles dans le SDK. Il s'agit du WebBrowserTask.

WebBrowserTask webBrowserTask = new WebBrowserTask();

webBrowserTask.Uri = new Uri("http://msdn.microsoft.com", UriKind.Absolute);

webBrowserTask.Show();

[C#] Le piège des paramètres nommés et optionnels

8. August 2011 07:08 by Renaud in   //  Tags:   //   Comments (2)

Dans cet article, je vais vous montrer un petit bout de code utilisant les paramètres nommés et optionnels. Ce code est très simple mais il risque fort de vous embrouiller. Et c'est normal, tout y est fait pour!

Si vous êtes encore étudiant, c'est bien le genre de truc vicieux qu'on pourrait vous demander lors d'un test :)

using System;
class Base {
    public virtual void Foo(int x = 4, int y = 5) {
        Console.WriteLine("x:{0}, y:{1}", x, y);
    }
}

class Derived : Base {
    public override void Foo(int y = 4, int x = 5) {
        Console.WriteLine("x:{0}, y:{1}", x, y);
    }
}

class Program {
    static void Main(string[] args) {
        Base b = new Derived();
        b.Foo(y: 5, x: 4);
    }
}
Quel sera le résultat affiché? x:4, y:4 x:4, y:5 x:5, y:4 x:5, y:5

Pendant que vous réfléchissez, je vous explique ce code plus en détail...

Il y a plusieurs choses à remarquer ici:

Les paramètres optionnels: depuis C# 4.0, il est possible de préciser une valeur par défaut pour les paramètres d'une méthode ou d'un constructeur. Si parmi les paramètres, certains n'ont pas de valeur par défaut, il doivent être placés avant les paramètres optionnels de sorte que le compilateur puissé déterminer quelle méthode est appelée sans ambiguïté! Cela permet d'écrire un peu moins de code, comme dans cet exemple:

        public Personne(string nom = "Sans nom", int age = "18"){
            Nom = nom;
            Age = age;
        }

Sans les paramètres optionnels, ce constructeur aurait été écrit avec trois constructeurs:

        public Personne() : this("Sans nom", 18) { }

        public Personne(string nom) : this(nom, 18) { }

        public Personne(string nom, int age){
            Nom = nom;
            Age = age;
        }

Les paramètres nommés: également depuis C#4.0, il est permis de placer des paramètres dans n'importe quel ordre en les nommant. Dans le premier morceau de code, on passe d'abord la valeur de y, et ensuite la valeur de x!

b.Foo(y: 5, x: 4);

La surcharge de méthode: la méthode Foo est virtual dans la classe Base, ce qui permet de la surcharger dans les sous-classe grâce au mot-clé override.

Mais revenons à notre problème:

        Base b = new Derived();
        b.Foo(y: 5, x: 4);

Puisqu'on a surchargé la méthode Foo dans la classe Derived, le polymorphisme va faire que c'est celle-là qui sera exécutée. Mais aussi étrange que cela puisse paraître, le résultat affiché est : x:5, y:4 On vient pourtant de préciser que x = 4 et y = 5! Qu'est-ce qu'il s'est passé alors?

L'explication est en fait très simple, et il suffit d'écrire ce code dans Visual Studio pour s'en rendre compte: si vous tapez b.Foo(, l'IntelliSense vous affiche la signature de la méthode de la classe Base. Cela est bien normal puisqu'on l'appel sur un objet b de type Base.

Lorsqu'on indique de passer  x = 4 et y = 5 à la méthode Foo, il faut donc comprendre qu'on ne parle pas des x et y de la méthode  void Foo(int y, int x) de la classe Derived mais bien de la classe Base! Evidemment, pour rendre la chose plus confuse, les noms ont été inversés dans la surcharge, mais nous aurions pu utiliser d'autres noms: Derived.Foo(int premier, int second).

La correspondance entre arguments d'une méthode virtual et une méthode surchargée se fait sur base de l'ordre ( comme le montre cet incroyable schéma :) ) et non pas du nom des paramètres!

Dans l'exercice, on passe donc  x = 4 et y = 5, en se basant sur les paramètres de la méthode de la classe Base. Ce qui donne y=4 et x=5 dans la méthode surchargée! Voilà pourquoi le résultat de l'impression est x:5, y:4!

C'est donc là qu'est le danger, qui n'en est pas vraiment un puisque Visual Studio clarifie cette situation grâce à l'IntelliSense!

Quoi qu'il en soit, vous voilà prévenus ! :)

[Solution] WP-PageNavi ne fonctionne pas avec Platform Free Edition

7. August 2011 04:08 by Renaud in   //  Tags:   //   Comments (4)
Edit du 10 septembre 2011: fonctionne pour Platform 1.3.5
Pour ce blog, j'utilise Platform dans sa version gratuite, un thème sous licence GNU. Il me semblait à priori normal de pouvoir utiliser un plug-in du style WP-PageNavi, qui permet de faciliter la navigation en remplaçant le peu élégant "← Previous entries / Next entries →" par ceci: Mais, évidemment, ça n'aurait pas été rigolo si tout avait fonctionné du premier coup. Je ne suis pas vraiment un spécialiste de WordPress...  J'ai commencé par installer quelques plugins similaires à celui que cité plus haut avant d'admettre que je n'y arriverais pas comme ça. Quel que soit le plugin testé, rien ne se passait. Finalement j'me suis dit que le thème y était peut-être pour quelque chose. Sorry but I haven't translated this post in english yet! Anyway, you can find the solution to this problem in my comment on the following post: [resolved] Does Platform theme(free edition) support wp-pagenavi plugin?  
Edit du 10 septembre 2011: fonctionne pour Platform 1.3.5
Pour ce blog, j'utilise Platform dans sa version gratuite, un thème sous licence GNU. Il me semblait à priori normal de pouvoir utiliser un plug-in du style WP-PageNavi, qui permet de faciliter la navigation en remplaçant le peu élégant "← Previous entries / Next entries →" par ceci: Mais, évidemment, ça n'aurait pas été rigolo si tout avait fonctionné du premier coup. Je ne suis pas vraiment un spécialiste de WordPress...  J'ai commencé par installer quelques plugins similaires à celui que cité plus haut avant d'admettre que je n'y arriverais pas comme ça. Quel que soit le plugin testé, rien ne se passait. Finalement j'me suis dit que le thème y était peut-être pour quelque chose. J'ai cherché dans les réglages, et ait trouvé ceci dans la catégorie Apparence > PageLines Settings > Template Setup : Voilà ce que je cherchais, le contrôle Pagination du template Posts Page Content! C'est lui qui est responsable de l'horrible "Previous / Next" en bas de page. Je remarque également qu'en cliquant sur Show Section Descriptions, on nous assure que WP-PageNavi est bien supporté. Quelque chose ne fonctionne donc pas correctement. En lisant le readme du WP-PageNavi, j'ai appris qu'on pouvait l'installer manuellement:
In your theme, replace code like this:
<div class="navigation">
	<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentyten' ) ); ?></div>
	<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?></div>
</div>
with this:
<?php wp_pagenavi(); ?>
Tout n'est pas perdu dans ce cas :) j'ai donc googlé vite fait tout ça pour trouver quel fichier du thème Platform concerne la pagination, et je découvre le coupable ! wp-content/themes/platform/sections/wp/section.pagination.php Vous pouvez éditer ce fichier en utilisant un client FTP comme FileZilla! Ce fichier contient la classe PageLinesPagination, qui correspond au contrôle Pagination en image ci-dessus! Et voici la partie qui nous intéresse:
function section_template() { ?>
		<?php if(function_exists('wp_pagenavi') && show_posts_nav() && VPRO):?>
			<?php wp_pagenavi(); ?>
		<?php elseif (show_posts_nav()) : ?>
			<div class="page-nav-default fix">
				<span class="previous-entries"><?php next_posts_link(__('&larr; Previous Entries','pagelines')) ?></span>
				<span class="next-entries"><?php previous_posts_link(__('Next Entries &rarr;','pagelines')) ?></span>
			</div><!-- page nav -->
		<?php endif;?>

	<?php }
Remarquez le "&& VPRO" dans le premier test. Cela signifie que même si WP-PageNavi est installé, on ne l'utilisera pas dans la version free de Platform, mais à la place on utilisera la navigation classique indiquée juste en-dessous! Pour que WP-PageNavi s'exécute correctement, il suffit donc d'éditer cette ligne et de supprimer la dernière condition:
<?php if(function_exists('wp_pagenavi') && show_posts_nav()):?>
Il ne reste plus qu'à bidouiller un peu le CSS du plugin pour centrer tout ça un minimum... Le seul bémol, c'est qu'à chaque mise à jour du thème, il faudra corriger cette ligne. J'ai pas vraiment cherché plus loin pour savoir comment faire une solution permanente. Si vous avez une proposition, elle sera la bienvenue dans les commentaires!
J'sais pas si ça valait vraiment la peine d'écrire un article là-dessus, j'avoue, mais ça m'a fait plaisir de trouver la solution et de vous la faire partager! :)
J'ai cherché dans les réglages, et ait trouvé ceci dans la catégorie Apparence > PageLines Settings > Template Setup : Voilà ce que je cherchais, le contrôle Pagination du template Posts Page Content! C'est lui qui est responsable de l'horrible "Previous / Next" en bas de page. Je remarque également qu'en cliquant sur Show Section Descriptions, on nous assure que WP-PageNavi est bien supporté. Quelque chose ne fonctionne donc pas correctement. En lisant le readme du WP-PageNavi, j'ai appris qu'on pouvait l'installer manuellement:
In your theme, replace code like this:
<div class="navigation">
	<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentyten' ) ); ?></div>
	<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?></div>
</div>
with this:
<?php wp_pagenavi(); ?>
Tout n'est pas perdu dans ce cas :) j'ai donc googlé vite fait tout ça pour trouver quel fichier du thème Platform concerne la pagination, et je découvre le coupable ! wp-content/themes/platform/sections/wp/section.pagination.php Vous pouvez éditer ce fichier en utilisant un client FTP comme FileZilla! Ce fichier contient la classe PageLinesPagination, qui correspond au contrôle Pagination en image ci-dessus! Et voici la partie qui nous intéresse:
function section_template() { ?>
		<?php if(function_exists('wp_pagenavi') && show_posts_nav() && VPRO):?>
			<?php wp_pagenavi(); ?>
		<?php elseif (show_posts_nav()) : ?>
			<div class="page-nav-default fix">
				<span class="previous-entries"><?php next_posts_link(__('&larr; Previous Entries','pagelines')) ?></span>
				<span class="next-entries"><?php previous_posts_link(__('Next Entries &rarr;','pagelines')) ?></span>
			</div><!-- page nav -->
		<?php endif;?>

	<?php }
Remarquez le "&& VPRO" dans le premier test. Cela signifie que même si WP-PageNavi est installé, on ne l'utilisera pas dans la version free de Platform, mais à la place on utilisera la navigation classique indiquée juste en-dessous! Pour que WP-PageNavi s'exécute correctement, il suffit donc d'éditer cette ligne et de supprimer la dernière condition:
<?php if(function_exists('wp_pagenavi') && show_posts_nav()):?>
Il ne reste plus qu'à bidouiller un peu le CSS du plugin pour centrer tout ça un minimum... Le seul bémol, c'est qu'à chaque mise à jour du thème, il faudra corriger cette ligne. J'ai pas vraiment cherché plus loin pour savoir comment faire une solution permanente. Si vous avez une proposition, elle sera la bienvenue dans les commentaires!
J'sais pas si ça valait vraiment la peine d'écrire un article là-dessus, j'avoue, mais ça m'a fait plaisir de trouver la solution et de vous la faire partager! :)

TextBox

About the author

I'm a developer, blog writer, and author, mainly focused on Microsoft technologies (but not only Smile). I'm Microsoft MVP Client Development since July 2013.

Microsoft Certified Professional

I'm currently working as an IT Evangelist with an awesome team at the Microsoft Innovation Center Belgique, where I spend time and energy helping people to develop their projects. I also give training to enthusiastic developers and organize afterworks with the help of the Belgian community.

MIC Belgique

Take a look at my first book (french only): Développez en HTML 5 pour Windows 8

Développez en HTML5 pour Windows 8

Membre de l'association Fier d'être développeur

TextBox

Month List