<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Blog des développeurs d'applications Windows 8</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/windowsappdev_fr/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/feed.xml</link>
    <description>Indications sur la conception d&amp;#039;applications de style Metro pour Windows 8, par l&amp;#039;équipe d&amp;#039;ingénierie de Windows 8</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:28:48 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Tout sur les promesses (pour les applications du Windows Store écrites en JavaScript)</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/tout-sur-les-promesses-pour-les-applications-du-windowsstore-crites-en-javascript</link>
      <pubDate>Wed, 26 Jun 2013 15:53:01 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/06/26/tout-sur-les-promesses-pour-les-applications-du-windowsstore-crites-en-javascript/</guid>
      <description><![CDATA[Lorsque vous développez des applications du Windows Store en JavaScript, vous rencontrez des...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Lorsque vous développez des applications du Windows Store en JavaScript, vous rencontrez des constructions appelées <i><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/Hh700339.aspx">promesses</a> </i>dès que vous réalisez une action impliquant une API asynchrone. En très peu de temps, vous pouvez écrire facilement des chaînes de promesses pour les opérations séquentielles asynchrones.</p>  <p>Au cours de votre travail de développement, vous rencontrerez cependant d'autres usages des promesses, dont les principes de fonctionnement peuvent paraître moins évidents. L'optimisation des fonctions de rendu des éléments d'un contrôle ListView est un bon exemple, comme le montre l'<a href="http://code.msdn.microsoft.com/windowsapps/ListView-performance-39fb71f0">exemple d'optimisation des performances de contrôle HTML ListView</a>. Nous examinerons cet exemple plus en détail dans un prochain billet. Vous pouvez également découvrir cette fabuleuse démonstration (dans une version légèrement modifiée) présentée par Josh Williams lors de son intervention à la conférence //build 2012, et intitulée <a href="https://channel9.msdn.com/Events/Build/2012/4-101">Deep Dive into WinJS</a> :</p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">list.reduce(<span style="color: rgb(0, 0, 255);">function</span> callback (prev, item, i) {<br />    <span style="color: rgb(0, 0, 255);">var</span> result = doOperationAsync(item);<br />    <span style="color: rgb(0, 0, 255);">return</span> WinJS.Promise.join({ prev: prev, result: result}).then(<span style="color: rgb(0, 0, 255);">function</span> (v) {<br />        console.log(i + <span style="color: rgb(0, 96, 128);">&quot;, item: &quot;</span> + item+ <span style="color: rgb(0, 96, 128);">&quot;, &quot;</span> + v.result);<br />    });<br />})<br /></pre>
  </div>
</blockquote>

<p>Cet extrait de code rejoint les promesses d'opérations asynchrones parallèles et fournit leur résultat de façon séquentielle, selon leur ordre d'apparition dans l'élément <i>list</i>. Si en examinant ce code, vous comprenez immédiatement son fonctionnement, vous pouvez passer ce billet ! Dans le cas contraire, examinons ensemble comment fonctionnent réellement les promesses et comment elles sont exprimées dans WinJS (la bibliothèque Windows pour JavaScript), afin de mieux comprendre les types de schémas mis en jeu.</p>

<h2>Une promesse ? De quoi s'agit-il exactement ? Les relations de promesse</h2>

<p>Commençons par établir une vérité fondamentale : une promesse n'est rien d'autre qu'une construction de code ou, si vous préférez, une convention d'appel. En tant que telles, les promesses n'ont aucune relation intrinsèque avec les opérations asynchrones, elles sont simplement très <i>utiles</i> dans ce contexte ! Une promesse est tout simplement un objet représentant une valeur pouvant être disponible à tel ou tel moment dans le futur, mais qui peut également être déjà disponible. À cet égard, la promesse est semblable à sa définition usuelle dans le cadre des relations humaines. Si je dis à quelqu'un « Je te promets que je vais t'apporter des croissants », il est parfaitement clair que je ne possède pas encore les croissants, mais que je suppose que je les <i>aurai</i> à un moment ou à un autre. Une fois que je les ai en ma possession, je les apporte à la personne en question.</p>

<p>Ainsi, une promesse implique une relation entre deux agents : l'<i>initiateur</i>, qui fait la promesse d'apporter telle ou telle marchandise, et le <i>consommateur</i>, qui est à la fois le destinataire de la promesse et des marchandises. Peu importe la manière dont l'initiateur parvient à obtenir les marchandises, cela ne concerne pas le destinataire. De même, le consommateur peut faire ce que bon lui semble de la promesse elle-même et des marchandises livrées. Il peut même partager les marchandises obtenues avec d'autres consommateurs.</p>

<p>La relation entre l'initiateur et le consommateur se compose de deux étapes : la <i>création</i> et la <i>réalisation</i>. Tous ces éléments sont indiqués sur le schéma ci-dessous.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0844.promise_diagram_577C7B9B.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0844.promise_5F00_diagram_5F00_577C7B9B.png"><img title="promise_diagram" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="promise_diagram" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0458.promise_diagram_thumb_0FBAF2B4.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0458.promise_5F00_diagram_5F00_thumb_5F00_0FBAF2B4.png" width="700" height="341" /></a></p>

<p>Le fait que la relation se compose de deux étapes explique pourquoi les promesses fonctionnent parfaitement avec une livraison asynchrone, comme le montre le déroulement du flux sur le schéma. Une fois que le consommateur reçoit l'accusé de réception de la demande (la promesse), il peut « faire sa vie » (de façon asynchrone) au lieu d'attendre (de façon synchrone). Par conséquent, le consommateur peut faire autre chose pendant qu'il attend que la promesse soit réalisée. Il peut par exemple répondre à d'autres demandes, ce qui est justement le but principal des API asynchrones. Que se passe-t-il si les marchandises sont déjà disponibles ? La promesse est réalisée immédiatement, ce qui transforme l'ensemble du processus en une sorte de convention d'appel synchrone.</p>

<p>Bien évidemment, cette relation est un peu plus complexe que cela. Au cours de votre vie, vous avez certainement déjà fait des promesses, et des personnes vous ont également fait des promesses. Bien que la plupart de ces promesses aient été réalisées, en pratique de nombreuses promesses ne sont pas tenues : le livreur de pizzas, par exemple, n'est pas à l'abri d'un accident de la circulation ! Les promesses non tenues font partie de la vie quotidienne, et nous devons accepter cet état de fait, aussi bien dans nos vies personnelles qu'en matière de programmation asynchrone.</p>

<p>Dans la relation de promesse, l'initiateur doit donc disposer d'une méthode pour signaler qu'il ne peut pas tenir sa promesse. De son côté, le consommateur doit disposer d'une méthode pour vérifier l'affirmation de l'initiateur. Deuxièmement, en tant que consommateurs, nous sommes parfois impatients quant aux promesses qui nous sont faites ! Par conséquent, si l'initiateur peut suivre la progression de la réalisation de sa promesse, le consommateur doit également disposer d'un moyen de recevoir cette information. Troisièmement, le consommateur peut également annuler sa commande et signaler à l'initiateur qu'il n'a plus besoin des marchandises.</p>

<p>En ajoutant ces besoins à notre schéma, nous disposons désormais d'une vue d'ensemble de la relation :</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/4251.promise_diagram_2_23D40F3D.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/4251.promise_5F00_diagram_5F00_2_5F00_23D40F3D.png"><img title="promise_diagram_2" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="promise_diagram_2" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0550.promise_diagram_2_thumb_1CB4D2C5.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0550.promise_5F00_diagram_5F00_2_5F00_thumb_5F00_1CB4D2C5.png" width="700" height="432" /></a></p>

<p>Examinons maintenant comment ces relations se manifestent dans le code.</p>

<h2>La construction de la promesse et les chaînes de promesses</h2>

<p>En matière de promesses, il existe en fait plusieurs propositions et spécifications. Celle utilisée dans Windows et WinJS porte le nom <a href="http://wiki.commonjs.org/wiki/Promises/A">Common JS/Promises A</a>. Elle formule une promesse, laquelle est renvoyée par un initiateur pour représenter une valeur à transmettre ultérieurement. Cette promesse prend la forme d'un objet associé à une fonction appelée <b>then</b>. Les consommateurs s'abonnement à la réalisation de la promesse en appelant la méthode <b>then</b>. (Dans Windows, les promesses prennent aussi en charge une fonction similaire appelée <b>done</b>, qui est utilisée dans les chaînes de promesses, comme nous le verrons très vite.)</p>

<p>Le consommateur transmet jusqu'à trois fonctions optionnelles à cette fonction, sous forme d'arguments, dans l'ordre suivant :</p>

<ol>
  <li>Un <i>gestionnaire Terminé</i>. L'initiateur appelle cette fonction lorsque la valeur promise est disponible. Si cette valeur est déjà disponible (<i>is </i>), le gestionnaire Terminé est appelé immédiatement (de façon synchrone) à partir de <b>then</b>.</li>

  <li>Un <i>gestionnaire d'erreurs</i> facultatif, appelé lorsqu'il s'avère impossible d'acquérir la valeur promise. Pour une promesse donnée, le gestionnaire Terminé n'est jamais appelé si le gestionnaire d'erreur l'a été.</li>

  <li>Un <i>gestionnaire de progression</i> facultatif, qui est appelé de façon périodique à partir de résultats intermédiaires, si l'opération prend en charge cette possibilité. (Dans WinRT, cela signifie que l'API a la valeur renvoyée <b>IAsync[Action | Operation]WithProgress</b>, celles dont la valeur est <b>IAsync[Action | Operation]</b> ne prenant pas en charge cette possibilité.)</li>
</ol>

<p>Sachez que vous pouvez transmettre la valeur <i>null</i> pour l'ensemble de ces arguments, par exemple lorsque vous souhaitez attacher uniquement un gestionnaire d'erreurs et non pas un gestionnaire Terminé. </p>

<p>De l'autre côté de la relation, un consommateur peut abonner autant de gestionnaires qu'il le souhaite à la même promesse, en appelant <b>then</b> à plusieurs reprises. Il peut également partager la promesse avec d'autres consommateurs, qui peuvent aussi appeler <b>then</b> pour leur propre contenu. Cette possibilité est intégralement prise en charge.</p>

<p>Par conséquent, une promesse doit gérer des listes contenant l'intégralité des gestionnaires qu'elle reçoit, et les appeler au moment adéquat. Les promesses doivent également pouvoir être annulées, comme nous l'avons expliqué dans notre description complète de la relation.</p>

<p>Autre exigence de la spécification <i>Promises A</i>, la méthode <b>then</b> renvoie elle-même une promesse. Cette deuxième promesse est réalisée lorsque le gestionnaire Terminé envoyé au premier appel de la méthode <b>promise.then</b> renvoie une valeur, la valeur renvoyée étant transmise en tant que résultat de cette deuxième promesse. Examinez le fragment de code suivant :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> promise1 = someOperationAsync();<br /><span style="color: rgb(0, 0, 255);">var</span> promise2 = promise1.then(<span style="color: rgb(0, 0, 255);">function</span> completedHandler1 (result1) { <span style="color: rgb(0, 0, 255);">return</span> 7103; } );<br />promise2.then(<span style="color: rgb(0, 0, 255);">function</span> completedHandler2 (result2) { });<br /></pre>
  </div>
</blockquote>

<p>Ici, la chaîne d'exécution consiste à démarrer <b>someOperationAsync</b>, qui renvoie <i>promise1</i>. Pendant que cette opération est en cours, nous appelons <b>promise1.then</b>, qui renvoie immédiatement <i>promise2</i>. Il va sans dire que la méthode <b>completedHandler1</b> n'est pas appelée, sauf si le résultat de l'opération asynchrone est déjà disponible. Supposons que nous attendons encore le résultat. Dans ce cas, nous appelons directement <b>promise2.then</b> et une là encore, la méthode completedHandler2 n'est <i>pas</i> appelée pour le moment.</p>

<p>Supposons que par la suite, la méthode <b>someOperationAsync</b> renvoie la valeur 14618. La promesse <i>promise1</i> est alors réalisée, et elle appelle donc <b>completedHandler1</b> en utilisant cette valeur. <i>result1</i> a donc la valeur 14618. <b>completedHandler1</b> s'exécute alors et renvoie la valeur 7103. À ce stade, la promesse <i>promise2</i> est réalisée, ce qui provoque l'appel de <b>completedHandler2</b> avec 7103 comme valeur <i>result2</i>.</p>

<p>Que se passe-t-il si un gestionnaire Terminé renvoie une autre promesse ? La situation est alors gérée de façon quelque peu différente. Supposons que la méthode <b>completedHandler1</b> du code ci-dessus renvoie une promesse comme celle-ci :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> promise2 = promise1.then(<span style="color: rgb(0, 0, 255);">function</span> completedHandler1 (result1) {<br />    <span style="color: rgb(0, 0, 255);">var</span> promise2a = anotherOperationAsync();<br />    <span style="color: rgb(0, 0, 255);">return</span> promise2a;<br />});<br /></pre>
  </div>
</blockquote>

<p>Dans ce cas, la valeur <i>result2</i> de <b>completedHandler2</b> ne correspond pas directement à <i>promise2a</i>, mais à la valeur <u>fulfillment</u> de <i>promise2a</i>. En effet, le gestionnaire Terminé renvoie une promesse, <i>promise2</i>, telle qu'elle est renvoyée par <b>promise1.then</b>, qui elle-même est réalisée en utilisant le résultat de <i>promise2a</i>.</p>

<p>C'est précisément cette caractéristique qui rend possible la création de chaînes d'opération séquentielles asynchrones, dans lesquelles le résultat de chaque opération de la chaîne est transmis à l'opération suivante. Dépourvues de variables intermédiaires et de gestionnaires nommés, les chaînes de promesses ressemblent souvent à ce modèle :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">operation1().then(<span style="color: rgb(0, 0, 255);">function</span> (result1) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation2(result1)<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result2) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation3(result2);<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result3) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation4(result3);<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result4) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation5(result4)<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result5) {<br />    <span style="color: rgb(0, 128, 0);">//And so on</span><br />});<br /></pre>
  </div>
</blockquote>

<p>Bien évidemment, chaque gestionnaire Terminé réalise en général d'autres opérations à partir du résultat reçu, mais cette structure de base reste commune à toutes les chaînes. Par ailleurs, toutes les méthodes <b>then</b> s'exécutent ici l'une après l'autre, car leur seule fonction consiste à enregistrer un gestionnaire Terminé spécifique et à renvoyer une autre promesse. Ainsi, à la fin du code, seule l'opération <i>operation1</i> a démarré et aucun gestionnaire Terminé n'a été appelé. En revanche, plusieurs promesses intermédiaires issues des appels de la méthode <b>then</b> ont été créées et reliées les unes aux autres, afin de gérer la chaîne à mesure que les opérations séquentielles se déroulent.</p>

<p>Il faut ici remarquer que la même séquence peut être exécutée en imbriquant chacune des opérations suivantes dans le gestionnaire Terminé précédent, auquel cas vous ne disposez pas d'instruction <i>return</i>. Cependant, ces imbrications peuvent conduire à un véritable casse-tête en termes de mise en retrait, en particulier si vous commencez à ajouter des gestionnaires de progression et d'erreurs à chaque appel de la méthode <b>then</b>.</p>

<p>D'ailleurs, les promesses de WinJS offrent notamment la fonctionnalité suivante : les erreurs qui ont lieu dans une partie de la chaîne sont automatiquement propagées en bout de chaîne. Par conséquent, vous pouvez en principe attacher un seul gestionnaire d'erreurs au dernier appel de la méthode <b>then</b>, au lieu de mettre en place des gestionnaires à chaque niveau. Cependant, pour différentes raisons assez subtiles, ces erreurs sont omises si le dernier lien de la chaîne est un appel de la méthode <b>then</b>. Pour cette raison, WinJS fournit également une méthode <b>done</b> pour les promesses. Cette méthode accepte les mêmes arguments que <b>then</b>, mais elle indique que la chaîne est terminée (elle renvoie la valeur <i>undefined</i> plutôt qu'une autre promesse). Un gestionnaire d'erreurs attaché à la méthode <b>done</b> est ensuite appelé pour gérer les erreurs de l'ensemble de la chaîne. En outre, en l'absence de gestionnaire d'erreurs, <b>done</b> émet une exception au niveau de l'application, où elle peut être gérée par les événements <b>window.onerror</b> de <b>WinJS.Application.onerror</b>. Pour simplifier, toutes les chaînes doivent idéalement se terminer par <b>done</b> pour faire en sorte que les exceptions apparaissent en surface et soient gérées correctement.</p>

<p>Bien évidemment, si vous écrivez une fonction dont le <i>but</i> est de renvoyer la dernière promesse d'une longue chaîne d'appels de la méthode <b>then</b>, vous utiliserez quand même <b>then</b> à la fin : la responsabilité du traitement des erreurs appartient ensuite à l'appelant, qui peut utiliser cette promesse dans une autre chaîne.</p>

<h2>Création de promesses : la classe WinJS.Promise</h2>

<p>Si vous pouvez dans tous les cas créer vos propres classes de promesses autour de la spécification <i>Promises A</i>, cela représente beaucoup de travail et il est préférable de faire appel à une bibliothèque. Pour cette raison, WinJS fournit une classe de promesses flexible, performante et rigoureusement testée, appelée <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211867.aspx"><b>WinJS.Promise</b></a>. Elle vous permet de créer facilement des promesses autour de différentes valeurs et opérations, sans devoir gérer les détails de la relation initiateur/consommateur, ni le comportement de la méthode <b>then</b>.</p>

<p>Lorsque vous en avez besoin, vous pouvez (et vous avez d'ailleurs tout intérêt à le faire) utiliser <b>new WinJS.Promise</b> ou une fonction d'assistance adaptée pour créer des promesses autour des opérations asynchrones et des valeurs existantes (synchrones). N'oubliez pas qu'une promesse n'est ni plus ni moins qu'une construction de code : elle ne doit pas obligatoirement inclure une opération asynchrone, ni <i>quoi que ce soit</i> dans un wrapper. De même, le simple fait d'inclure un morceau de code dans un wrapper au sein d'une promesse ne <i>rend</i> pas pour autant son exécution asynchrone<i>. </i>C'est en effet à vous de réaliser ce travail.</p>

<p>Pour prendre un exemple d'utilisation simple et direct de <b>WinJS.Promise</b>, supposons que nous souhaitons réaliser un calcul long (ajouter différents nombres de 1 à une valeur maximale) de façon asynchrone. Nous pourrions inventer notre propre mécanisme de rappel pour une telle routine, mais si nous l'incluons dans un wrapper, nous pouvons le joindre aux promesses d'autres API ou l'assembler sous forme de chaîne à ces promesses. (À ce propos, la fonction <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229787.aspx"><b>WinJS.xhr</b></a> inclut la demande asynchrone <b>XmlHttpRequest</b> de JavaScript dans un wrapper au sein d'une promesse, et vous n'avez donc pas à vous préoccuper de la structure d'événements spécifique de cette dernière.)</p>

<p>Nous pouvons évidemment utiliser un processus de travail JavaScript pour réaliser le calcul long, mais pour les besoins de notre illustration, nous allons le laisser sur le thread d'interface utilisateur et utiliser <b>setImmediate</b> pour diviser l'opération en plusieurs étapes. Voici comment implémenter cette méthode dans une structure de promesse en utilisant <b>WinJS.Promise</b> :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> calculateIntegerSum(max, step) {<br />    <span style="color: rgb(0, 128, 0);">//The WinJS.Promise constructor's argument is an initializer function that receives </span><br />    <span style="color: rgb(0, 128, 0);">//dispatchers for completed, error, and progress cases.</span><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (completeDispatch, errorDispatch, progressDispatch) {<br />        <span style="color: rgb(0, 0, 255);">var</span> sum = 0;<br /><br />        <span style="color: rgb(0, 0, 255);">function</span> iterate(args) {<br />            <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = args.start; i &lt; args.end; i++) {<br />                sum += i;<br />            };<br /><br />            <span style="color: rgb(0, 0, 255);">if</span> (i &gt;= max) {<br />                <span style="color: rgb(0, 128, 0);">//Complete--dispatch results to completed handlers</span><br />                completeDispatch(sum);<br />            } <span style="color: rgb(0, 0, 255);">else</span> {<br />                <span style="color: rgb(0, 128, 0);">//Dispatch intermediate results to progress handlers</span><br />                progressDispatch(sum);<br />                setImmediate(iterate, { start: args.end, end: Math.min(args.end + step, max) });<br />            }<br />        }<br />            <br />        setImmediate(iterate, { start: 0, end: Math.min(step, max) });<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>Lorsque la méthode <b>new WinJS.Promise</b> est appelée, le seul argument de son constructeur est une fonction <i>initializer</i> (qui est anonyme, dans notre cas). L'initialiseur encapsule l'opération à réaliser, mais sachez que la fonction elle-même s'exécute <i>de façon synchrone</i> sur le thread d'interface utilisateur. Par conséquent, si nous devions simplement réaliser un calcul long sans utiliser <b>setImmediate</b>, nous bloquerions intégralement le thread d'interface utilisateur à ce stade. Rappelons que le fait de placer du code dans une promesse ne le<i> </i>rend pas automatiquement asynchrone : la fonction de l'initialiseur doit configurer elle-même ce paramètre.</p>

<p>En termes d'arguments, la fonction d'initialiseur reçoit trois <i>répartiteurs</i> pour les différents cas pris en charge par les promesses (opération terminée, erreur et progression). Comme vous pouvez le constater, nous appelons ces répartiteurs à certains moments bien précis au cours de l'opération, en utilisant les arguments appropriés.</p>

<p>J'appelle ces fonctions des « répartiteurs », car ils ne jouent pas le même rôle que les gestionnaires que les consommateurs abonnent à la méthode <b>then</b> de la promesse (ou à la méthode <b>done</b>, comme vous le savez désormais). En arrière-plan, WinJS gère des tableaux de gestionnaires, ce qui permet à un nombre illimité de consommateurs de s'abonner à un nombre illimité de gestionnaires. Lorsque vous appelez l'un de ces répartiteurs, WinJS réalise une itération au sein de sa liste interne et appelle de votre part l'ensemble de ces gestionnaires. <b>WinJS.Promise</b> s'assure également que sa méthode <b>then</b> renvoie une autre promesse, car cela est requis pour former une chaîne.</p>

<p>Pour résumer, <b>WinJS.Promise</b> fournit l'ensemble des détails qui entourent une promesse. Vous pouvez ainsi vous concentrer sur l'opération centrale représentée par la promesse, qui prend la forme de la fonction d'initialiseur.</p>

<h2>Fonctions d'assistance pour la création de promesses</h2>

<p>La principale fonction d'assistance permettant de créer une promesse est la méthode statique <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211664.aspx"><b>WinJS.Promise.as</b></a>, qui inclut dans un wrapper <i>n'importe quelle valeur</i> au sein d'une promesse. Un tel wrapper sur une valeur existante se retourne et appelle le gestionnaire Terminé transmis à la méthode <b>then</b>. Ceci vous permet plus précisément de traiter les valeurs arbitraires connues comme des promesses, que vous pouvez entremêler et mélanger (en les liant ou en les regroupant en chaîne) à d'autres promesses. En utilisant <b>as</b> sur une promesse existante, cette promesse est renvoyée.</p>

<p>L'autre fonction d'assistance statique est <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229729.aspx"><b>WinJS.Promise.timeout</b></a>, qui fournit un wrapper très pratique autour de <b>setTimeout</b> et <b>setImmediate</b>. Vous pouvez également créer une promesse qui annule une seconde promesse si cette dernière n'est pas réalisée au bout d'un certain nombre de millisecondes.</p>

<p>Sachez que les promesses <b>timeout</b> qui entourent <b>setTimeout</b> et <b>setImmediate</b> sont elles-mêmes réalisées avec la valeur <i>undefined</i>. Une question revient souvent : « Comment ces promesses peuvent-elles être utilisées pour fournir un autre résultat une fois le délai expiré ? ». Pour trouver la réponse, rappelons que <b>then</b> renvoie une autre promesse qui est réalisée avec la valeur renvoyée par le gestionnaire Terminé. Prenons par exemple cette ligne de code :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> p = WinJS.Promise.timeout(1000).then(<span style="color: rgb(0, 0, 255);">function</span> () { <span style="color: rgb(0, 0, 255);">return</span> 12345; });</pre>
  </div>
</blockquote>

<p>Elle crée la promesse <i>p</i>, qui sera réalisée avec la valeur 12345 au bout d'une seconde. En d'autres termes, <b>WinJS.Promise.timeout(…).then(function () { return &lt;valeur>} )</b> est un schéma qui permet de renvoyer <i>&lt;valeur></i> au bout du délai d'expiration donné. Si la valeur <i>&lt;valeur></i> est elle-même une autre promesse, l'opération revient alors à fournir la valeur de réalisation de cette promesse au bout d'un certain temps après l'expiration du délai.</p>

<h2>Annulation et génération d'erreurs de promesse</h2>

<p>Dans le code que nous venons d'examiner, vous avez peut-être remarqué trois problèmes. En premier lieu, il est impossible d'annuler l'opération une fois qu'elle a démarré. Deuxièmement, le traitement des erreurs n'est pas vraiment optimal.</p>

<p>Dans les deux cas, le problème est que les fonctions qui créent une promesse, par exemple <b>calculateIntegerSum</b>, doivent toujours renvoyer une promesse. Si une opération ne se termine pas ou n'est jamais démarrée, la promesse se retrouve à l'<i>état d'erreur</i>. Par conséquent, la promesse n'a pas de résultat à transmettre aux gestionnaires Terminé et n'en aura d'ailleurs <i>jamais</i> : elle appelle uniquement ses gestionnaires d'erreurs. En effet, si un consommateur appelle la méthode <b>then</b> pour une promesse qui se trouve déjà en état d'erreur, cette promesse appelle immédiatement (de façon synchrone) le gestionnaire d'erreurs indiqué à la méthode <b>then</b>.</p>

<p>Une promesse <b>WinJS.Promise</b> peut entrer dans un état d'erreur pour deux raisons : si le consommateur appelle sa méthode <b>cancel</b> ou si le code de la fonction d'initialiseur appelle le répartiteur d'erreurs. Lorsque cela se produit, les gestionnaires d'erreurs reçoivent la valeur d'erreur interceptée ou propagée dans la promesse. Si vous créez une opération dans une promesse <b>WinJS.Promise</b>, vous pouvez également utiliser une instance de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211689.aspx"><b>WinJS.ErrorFromName</b></a>. Il s'agit simplement d'un objet JavaScript contenant une propriété <i>name</i> qui identifie l'erreur et une propriété <i>message</i> offrant plus de détails. Par exemple, lorsqu'une promesse est annulée, les gestionnaires d'erreurs reçoivent un objet d'erreur dont les propriétés <i>name</i> et <i>message</i> portent la valeur « Canceled ».</p>

<p>Mais que faire si vous ne pouvez même pas démarrer l'opération ? Par exemple, si vous appelez la méthode <b>calculateIntegerSum</b> en utilisant des arguments incorrects (0, 0, par exemple), en principe elle n'essaie même pas de lancer le décompte et renvoie une promesse dans un état d'erreur. C'est le but de la méthode statique <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229784.aspx"><b>WinJS.Promise.wrapError</b></a>. Elle accepte comme paramètre une instance de <b>WinJS.ErrorFromName</b> et renvoie une promesse dans un état d'erreur, qui dans ce cas est renvoyée en lieu et place d'une nouvelle instance <b>WinJS.Promise</b>.</p>

<p>Autre partie importante, bien qu'un appel de la méthode <b>cancel</b> de la promesse met la promesse elle-même dans un état d'erreur, comment faire pour arrêter l'opération asynchrone en cours ? Dans l'implémentation précédente de <b>calculateIntegerSum</b>, la méthode <b>setImmediate</b> est appelée de façon répétée jusqu'à ce que l'opération soit terminée, quel que soit l'état de la promesse que nous avons créée. En effet, si l'opération appelle le répartiteur Terminé après l'annulation de la promesse, cette dernière ignore que l'opération est terminée.</p>

<p>Ensuite, nous devons faire en sorte que la promesse signale à l'opération qu'elle n'a plus besoin de poursuivre son travail. Pour cette raison, le constructeur <b>WinJS.Promise</b> accepte un deuxième argument de fonction, qui est appelé en cas d'annulation de la promesse. Dans notre exemple, l'appel de cette fonction doit pouvoir empêcher l'appel suivant de la méthode <b>setImmediate</b>, pour arrêter ainsi le calcul. Voici à quoi ressemble le code une fois que la gestion des erreurs a été améliorée :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> calculateIntegerSum(max, step) {<br />    <span style="color: rgb(0, 128, 0);">//Return a promise in the error state for bad arguments</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (max &lt; 1 || step &lt; 1) {<br />        <span style="color: rgb(0, 0, 255);">var</span> err = <span style="color: rgb(0, 0, 255);">new</span> WinJS.ErrorFromName(<span style="color: rgb(0, 96, 128);">&quot;calculateIntegerSum&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;max and step must be 1 or greater&quot;</span>);<br />        <span style="color: rgb(0, 0, 255);">return</span> WinJS.Promise.wrapError(err);<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">var</span> _cancel = <span style="color: rgb(0, 0, 255);">false</span>;<br /><br />    <span style="color: rgb(0, 128, 0);">//The WinJS.Promise constructor's argument is an initializer function that receives </span><br />    <span style="color: rgb(0, 128, 0);">//dispatchers for completed, error, and progress cases.</span><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (completeDispatch, errorDispatch, progressDispatch) {<br />        <span style="color: rgb(0, 0, 255);">var</span> sum = 0;<br /><br />        <span style="color: rgb(0, 0, 255);">function</span> iterate(args) {<br />            <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = args.start; i &lt; args.end; i++) {<br />                sum += i;<br />            };<br /><br />            <span style="color: rgb(0, 128, 0);">//If for some reason there was an error, create the error with WinJS.ErrorFromName</span><br />            <span style="color: rgb(0, 128, 0);">//and pass to errorDispatch</span><br />            <span style="color: rgb(0, 0, 255);">if</span> (<span style="color: rgb(0, 0, 255);">false</span> <span style="color: rgb(0, 128, 0);">/* replace with any necessary error check -- we don’t have any here */</span>) {<br />                errorDispatch(<span style="color: rgb(0, 0, 255);">new</span> WinJS.ErrorFromName(<span style="color: rgb(0, 96, 128);">&quot;calculateIntegerSum (scenario 7)&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;error occurred&quot;</span>));<br />            }<br /><br />            <span style="color: rgb(0, 0, 255);">if</span> (i &gt;= max) {<br />                <span style="color: rgb(0, 128, 0);">//Complete--dispatch results to completed handlers</span><br />                completeDispatch(sum); <br />            } <span style="color: rgb(0, 0, 255);">else</span> {<br />                <span style="color: rgb(0, 128, 0);">//Dispatch intermediate results to progress handlers</span><br />                progressDispatch(sum);<br /><br />                <span style="color: rgb(0, 128, 0);">//Interrupt the operation if canceled</span><br />                <span style="color: rgb(0, 0, 255);">if</span> (!_cancel) {<br />                    setImmediate(iterate, { start: args.end, end: Math.min(args.end + step, max) });<br />                }<br />            }<br />        }<br />            <br />        setImmediate(iterate, { start: 0, end: Math.min(step, max) });<br />    },<br />    <span style="color: rgb(0, 128, 0);">//Cancellation function for the WinJS.Promise constructor</span><br />    <span style="color: rgb(0, 0, 255);">function</span> () {<br />        _cancel = <span style="color: rgb(0, 0, 255);">true</span>;<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>Au final, le fait de créer plusieurs instances de <b>WinJS.Promise</b> permet plusieurs usages. Par exemple, si vous disposez d'une bibliothèque qui communique avec un service Web par le biais d'une autre méthode asynchrone, vous pouvez inclure ces opérations dans un wrapper au sein des promesses. Vous pouvez également utiliser une nouvelle promesse pour combiner dans une seule promesse plusieurs opérations asynchrones (ou d'autres promesses) issues de différentes sources, afin de contrôler toutes les relations concernées. Dans le code d'un initialiseur de <b>WinJS.Promise</b>, vous pouvez évidemment intégrer vos propres gestionnaires pour d'autres opérations asynchrones et leurs promesses. Ces gestionnaires peuvent être utilisés pour encapsuler des mécanismes de relance automatique en cas d'expiration des délais réseau, par exemple, pour se raccorder à une interface générique de progression de mise à jour ou encore pour ajouter des fonctionnalités d'arrière-plan de journalisation ou d'analyse d'audience. Dans tous ces cas, le reste de votre code n'a jamais besoin de connaître les détails et peut simplement traiter les promesses du côté consommateur.</p>

<p>Dans le même esprit, il est relativement simple d'inclure un processus de travail JavaScript dans un wrapper au sein d'une promesse, pour qu'il ressemble à d'autres opérations asynchrones dans WinRT et qu'il se comporte de la même manière. Comme vous le savez peut-être, les processus de travail envoient leurs résultats par le biais d'un appel <b>postMessage</b> qui émet un événement <b>message</b> sur l'objet du processus de travail de l'application. Le code suivant relie ensuite cet événement à une promesse réalisée avec les résultats qui sont fournis dans le message :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 128, 0);">// This is the function variable we're wiring up.</span><br /><span style="color: rgb(0, 0, 255);">var</span> workerCompleteDispatch = <span style="color: rgb(0, 0, 255);">null</span>;<br /><br /><span style="color: rgb(0, 0, 255);">var</span> promiseJS = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (completeDispatch, errorDispatch, progressDispatch) {<br />    workerCompleteDispatch = completeDispatch;<br />});<br /><br /><span style="color: rgb(0, 128, 0);">// Worker is created here and stored in the 'worker' variable</span><br /><br /><span style="color: rgb(0, 128, 0);">// Listen for worker events</span><br />worker.onmessage = <span style="color: rgb(0, 0, 255);">function</span> (e) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (workerCompleteDispatch != <span style="color: rgb(0, 0, 255);">null</span>) {<br />        workerCompleteDispatch(e.data.results); <span style="color: rgb(0, 128, 0);">/* event args depends on the worker */</span><br />    }<br />}<br /><br />promiseJS.done(<span style="color: rgb(0, 0, 255);">function</span> (result) {<br />    <span style="color: rgb(0, 128, 0);">// Output for JS worker</span><br />});<br /></pre>
  </div>
</blockquote>

<p>Pour élargir ce code en vue de gérer les erreurs issues du processus de travail, vous devez enregistrer le répartiteur d'erreurs dans une autre variable, faire en sorte que le gestionnaire d'événements <b>message</b> vérifie les informations d'erreur dans ses arguments d'événement, puis appeler le répartiteur d'erreurs en lieu et place du répartiteur Terminé.</p>

<h2>Joindre des promesses parallèles</h2>

<p>Comme les promesses sont souvent utilisées pour inclure des opérations asynchrones dans un wrapper, il est tout à fait possible que plusieurs opérations soient en cours au même moment. Dans ce cas, il peut être utile de savoir à quel moment l'une des promesses d'un groupe est réalisée ou à quel moment toutes les promesses du groupe sont réalisées. Les fonctions statiques <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229660.aspx"><b>WinJS.Promise.any</b></a> et <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211774.aspx"><b>WinJS.Promise.join</b></a> sont justement là pour ça.</p>

<p>Les deux fonctions acceptent un tableau de valeurs ou un objet comportant des propriétés de valeur. Ces valeurs peuvent être des promesses, et les éventuelles valeurs qui ne sont pas des promesses sont incluses dans un wrapper avec <b>WinJS.Promise.as</b>, de telle sorte que l'intégralité du tableau ou de l'objet se compose de promesses.</p>

<p>Voici les caractéristiques de la méthode <b>any</b> :</p>

<ul>
  <li><b>any</b> crée une seule promesse qui est réalisée lorsque l'une de ses promesses est réalisée ou échoue en raison d'une erreur (OU logique). En substance, <b>any</b><i> </i>rattache les gestionnaires Terminé à toutes ces promesses et dès qu'un gestionnaire Terminé est appelé, il appelle les gestionnaires Terminé que la promesse <b>any</b><i> </i>a elle-même reçu.</li>

  <li>Une fois que la promesse <b>any</b><i> </i>est réalisée (c'est-à-dire lorsque la première promesse de la liste est réalisée), les autres opérations de la liste sont exécutées, en appelant les gestionnaires Terminé, les gestionnaires d'erreur ou les gestionnaires de progression affectés individuellement aux différentes promesses.</li>

  <li>Si vous annulez la promesse à partir de <b>any</b>, toutes les promesses de la liste sont annulées.</li>
</ul>

<p>En ce qui concerne <b>join</b> :</p>

<ul>
  <li><b>join</b> crée une seule promesse qui est réalisée lorsque <i>toutes</i> ses promesses sont réalisées ou échouent en raison d'une erreur (ET logique). En substance, <b>join</b><i> </i>rattache les gestionnaires Terminé et les gestionnaires d'erreurs à toutes ces promesses, et attend que tous ces gestionnaires aient été appelés, avant d'appeler les gestionnaires Terminé qu'elle a elle-même reçu.</li>

  <li>La promesse <b>join</b> signale également sa progression aux éventuels gestionnaires de progression que vous fournissez. Dans ce cas, le résultat intermédiaire est un tableau de résultats issus des promesses individuelles réalisées jusque là.</li>

  <li>Si vous annulez la promesse à partir de <b>join</b>, toutes les promesses en attente sont annulées.</li>
</ul>

<p>En dehors de <b>any</b> et <b>join</b>, il existe deux autres méthodes statiques <b>WinJS.Promise</b> à connaître, car elles peuvent s'avérer pratiques :</p>

<ul>
  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211765.aspx"><b>is</b></a> détermine si une valeur arbitraire est une promesse et renvoie une valeur booléenne. Pour simplifier, elle vérifie qu'il s'agit d'un objet comportant une fonction appelée « then » et ne teste pas « done ».</li>

  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229727.aspx"><b>theneach</b></a><i> </i>applique des gestionnaires Terminé, des gestionnaires d'erreurs et des gestionnaires de progression à un groupe de promesses (en utilisant <b>then</b>) et renvoie les résultats sous forme d'un groupe de valeurs au sein d'une promesse. La valeur des gestionnaires peut être <i>null</i>.</li>
</ul>

<h2>Promesses parallèles avec résultats séquentiels</h2>

<p>Avec <b>WinJS.Promise.join</b> et <b>WinJS.Promise.any</b>, nous pouvons travailler avec des promesses parallèles, c'est-à-dire avec des opérations parallèles asynchrones. La promesse renvoyée par <b>join</b> est là encore réalisée lorsque toutes les promesses d'un tableau sont réalisées. Cependant, il est fort probable que ces promesses se réalisent dans un ordre aléatoire. Comment faire si vous disposez d'un ensemble d'opérations qui peuvent s'exécuter de cette manière, mais que vous souhaitez traiter leurs résultats dans un ordre bien défini, c'est-à-dire dans l'ordre dans lequel leurs promesses apparaissent dans le tableau ?</p>

<p>Pour parvenir au but escompté, vous devez joindre chaque promesse suivante à la méthode <b>join</b> de toutes les méthodes précédentes. Le petit extrait de code qui figure au début de ce billet réalise précisément cette opération. Voici de nouveau le code, légèrement réécrit pour rendre les promesses plus explicites. (Supposez que <i>list</i><b> </b>est un tableau de valeurs utilisées comme arguments d'un appel asynchrone <b>doOperationAsync</b> susceptible de générer une promesse) :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">list.reduce(<span style="color: rgb(0, 0, 255);">function</span> callback (prev, item, i) {<br />    <span style="color: rgb(0, 0, 255);">var</span> opPromise = doOperationAsync(item);<br />    <span style="color: rgb(0, 0, 255);">var</span> join = WinJS.Promise.join({ prev: prev, result: opPromise});<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> join.then(<span style="color: rgb(0, 0, 255);">function</span> completed (v) {<br />        console.log(i + <span style="color: rgb(0, 96, 128);">&quot;, item: &quot;</span> + item+ <span style="color: rgb(0, 96, 128);">&quot;, &quot;</span> + v.result);<br />    });<br />})<br /></pre>
  </div>
</blockquote>

<p>Pour comprendre ce code, nous devons tout d'abord comprendre comment fonctionne la méthode <a href="http://msdn.microsoft.com/fr-fr/library/ie/ff679975(v=vs.94).aspx"><b>reduce</b></a> du tableau. Pour chaque élément du tableau, <b>reduce</b> appelle l'argument de fonction ici appelé <b>callback</b>, qui reçoit quatre arguments (seuls trois d'entre eux sont utilisés dans le code) :</p>

<ul>
  <li><i>prev</i> Valeur renvoyée par l'appel <i>précédent</i> de <b>callback</b> (valeur <i>null</i> pour le premier élément).</li>

  <li><i>item</i> Valeur actuelle issue du tableau.</li>

  <li><i>i</i> Index de l'élément dans la liste.</li>

  <li><i>source</i> Tableau d'origine.</li>
</ul>

<p>Pour le premier élément de la liste, nous obtenons une promesse que j'appellerai <b>opPromise<sub>1</sub></b>. Comme la valeur de <b>prev</b> est <i>null</i>, nous joignons <b>[WinJS.Promise.as(null), opPromise<sub>1</sub>]</b>. Remarquez cependant que nous ne renvoyons pas la méthode <b>join</b> elle-même. En lieu et place, nous attachons un gestionnaire Terminé (que j'ai appelé <b>completed</b>) à cette méthode join et renvoyons la promesse de sa méthode <b>then</b>.</p>

<p>N'oubliez pas que la promesse renvoyée par <b>then</b> sera réalisée lorsque le gestionnaire Terminé renverra une valeur. Par conséquent, nous renvoyons à partir de <b>callback</b> une promesse qui n'est pas réalisée tant que le gestionnaire <b>completed</b> du premier élément n'a pas traité les résultats de <b>opPromise<sub>1</sub></b>. Si vous regardez le résultat d'une méthode join, elle est réalisée au moyen d'un objet contenant les résultats issus des promesses de la liste d'origine. Par conséquent, la valeur de réalisation <i>v</i> contiendra à la fois une propriété <i>prev</i> et une propriété <i>result</i>, la valeur de cette dernière correspondant au résultat de <b>opPromise<sub>1</sub></b>.</p>

<p>Avec l'élément suivant de <i>list</i>, <b>callback</b> reçoit une propriété <i>prev</i> qui contient la promesse issue de la méthode <b>join.then</b> précédente. Nous créons ensuite une nouvelle jointure de <b>opPromise<sub>1</sub>.then</b> et <b>opPromise<sub>2</sub></b>. Par conséquent, cette jointure ne se termine pas tant que <b>opPromise<sub>2</sub></b> n'a pas été réalisée <i>et</i> que le gestionnaire Terminé de <b>opPromise<sub>1</sub></b> n'a pas renvoyé de valeur. Et voilà ! Le gestionnaire <b>completed<sub>2</sub></b> que nous attachons à cette méthode <b>join</b> n'est pas appelé tant que <b>completed<sub>1</sub></b> n'a pas renvoyé de valeur.</p>

<p>Les mêmes dépendances sont progressivement construites pour chaque élément de la liste. La promesse issue de <b>join.then</b> pour l'élément <i>n</i> n'est pas réalisée tant que <b>completed<i><sub>n</sub></i></b> ne renvoie pas de valeur. Ainsi, les gestionnaires Terminé sont forcément appelés dans le même ordre que <i>list</i>.</p>

<h2>Pour conclure</h2>

<p>Dans ce billet, nous avons constaté qu'une promesse n'est en substance qu'une construction de code ou une convention d'appel (quoique très puissante), qui permet de représenter une relation spécifique entre un initiateur, qui doit fournir des valeurs à une heure ultérieure arbitraire, et un consommateur, qui souhaite savoir quand ces valeurs sont disponibles. Ainsi, les promesses sont idéales pour représenter des résultats issus d'opérations asynchrones. Elles sont très souvent utilisées dans les applications du Windows Store écrites en JavaScript. La spécification des promesses permet également la création de chaînes d'opérations séquentielles asynchrones, chaque résultat intermédiaire passant d'un lien à un autre.</p>

<p>WinJS, la Bibliothèque Windows pour JavaScript, fournit une implémentation fiable des promesses, que vous pouvez utiliser pour inclure dans un wrapper n'importe quel type d'opération de votre choix. Elle fournit également des fonctions d'assistance pour certains scénarios courants, par exemple pour regrouper des promesses dans le cadre d'opérations parallèles. Grâce aux avantages de WinJS, vous pouvez travailler de façon très efficace avec des opérations asynchrones.</p>

<p>Kraig Brockschmidt 
  <br />Chef de projet, équipe Écosystème Windows 

  <br />Auteur de <a href="http://blogs.msdn.com/b/microsoft_press/archive/2012/10/29/free-ebook-programming-windows-8-apps-with-html-css-and-javascript.aspx"><i>Programming Windows 8 Apps in HTML, CSS, and JavaScript</i></a></p>

<!-- Title: “Tout sur les promesses (pour les applications du Windows Store écrites en JavaScript)” Tags: “JavaScript, applications du Windows Store, promesses” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Optimisation du rendu des éléments du contrôle ListView</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/optimisation-du-rendu-des-lments-du-contrle-listview</link>
      <pubDate>Tue, 25 Jun 2013 14:26:44 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/06/25/optimisation-du-rendu-des-lments-du-contrle-listview/</guid>
      <description><![CDATA[Pour de nombreuses applications du Windows Store écrites en JavaScript qui utilisent les...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Pour de nombreuses <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211385.aspx" target="_blank">applications du Windows Store écrites en JavaScript</a> qui utilisent les collections, une coopération appropriée avec le <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211837.aspx" target="_blank">contrôle ListView WinJS</a> est essentielle pour optimiser leurs performances. Ceci n'est pas surprenant : lorsque vous devez gérer et afficher des milliers d'éléments potentiels, toutes les optimisations que vous réalisez sur ces éléments font la différence. Ce qui compte le plus, c'est la manière dont chacun de ces éléments est rendu, c'est-à-dire comment (et quand) chaque élément du contrôle ListView est élaboré dans le DOM et apparaît dans l'application. En effet, la composante <i>quand </i>de cette équation devient un facteur critique lorsqu'un utilisateur se déplace rapidement dans une liste et s'attend à ce que cette liste soutienne le rythme qu'il lui impose.</p>  <p>Le rendu des éléments dans un contrôle ListView se produit via un modèle déclaratif défini en HTML ou via une <i>fonction de rendu</i> JavaScript personnalisée qui est appelée pour chaque élément de la liste. Même si l'utilisation d'un modèle déclaratif est la méthode la plus simple, elle ne confère pas une latitude très importante pour contrôler précisément le processus. Une fonction de rendu, d'un autre côté, vous permet de personnaliser le rendu élément par élément et de mettre en œuvre différentes optimisations qui sont illustrées dans l'<a href="http://code.msdn.microsoft.com/windowsapps/ListView-performance-39fb71f0" target="_blank">exemple d'optimisation des performances de contrôle HTML ListView</a>. Ces optimisations sont les suivantes :</p>  <ul>   <li>Autoriser la distribution asynchrone des données des éléments et d'un élément rendu. Ceci est pris en charge par les fonctions de rendu élémentaires.</li>    <li>Séparer la création de la forme d'un élément, qui est nécessaire à la disposition globale du contrôle ListView, de ses éléments internes. Ceci est pris en charge via un convertisseur d'espace réservé.</li>    <li>Réutiliser un élément créé au préalable (et ses enfants) en remplaçant ses données, ce qui évite la plupart des étapes de création d'un élément. Ceci est possible via un convertisseur d'espace réservé de recyclage.</li>    <li>Reporter les opérations visuelles intensives, telles que le chargement d'images et les animations, jusqu'à ce qu'un élément soit visible et tant que le contrôle ListView n'est pas déplacé rapidement. Ceci s'effectue via un convertisseur à plusieurs phases.</li>    <li>Traiter par lot les opérations visuelles identiques afin de limiter la répétition des rendus du DOM avec un convertisseur par lot à plusieurs phases.</li> </ul>  <p>Dans ce billet, nous allons examiner toutes ces étapes et voir comment elles coopèrent avec le processus de rendu des éléments du contrôle ListView. Comme vous pouvez l'imaginer, les optimisations qui entourent le <i>moment où</i> les éléments sont rendus entraînent un grand nombre d'opérations asynchrones et véhiculent par conséquent beaucoup de promesses. Au cours du processus, nous allons également acquérir une connaissance plus approfondie des promesses, en nous appuyant sur le billet précédent <a href="http://blogs.msdn.com/b/windowsappdev/archive/2013/06/10/all-about-promises-for-windows-store-apps-written-in-javascript.aspx" target="_blank">Tout sur les promesses</a> de ce blog.</p>  <p>De manière générale pour tous les convertisseurs, il est important de toujours ramener au minimum le temps de rendu des principaux éléments (sans compter les opérations reportées). Comme les performances finales du contrôle ListView dépendent de beaucoup du bon alignement de ses mises à jour sur les intervalles d'actualisation de l'écran, quelques millisecondes supplémentaires dans un convertisseur d'élément peut faire dépasser le temps de rendu global du contrôle ListView sur le prochain intervalle d'actualisation, entraînant la suppression d'images et des irrégularités visuelles. En d'autres termes, il est réellement très important d'optimiser votre code JavaScript dans les convertisseurs d'éléments.</p>  <h2>Convertisseurs élémentaires</h2>  <p>Commençons par passer rapidement en revue la fonction de rendu des éléments (que je vais simplement appeler <i>convertisseur</i>. Un convertisseur est une fonction que vous attribuez à la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh700705.aspx" target="_blank">itemTemplate</a> du contrôle ListView à la place d'un nom de modèle. Cette fonction est appelée, lorsque cela est nécessaire, pour les éléments que le contrôle ListView souhaite inclure dans le DOM. (Vous trouverez une documentation élémentaire sur les convertisseurs à la page <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh700705.aspx" target="_blank">itemTemplate</a>, mais l'exemple illustre mieux les optimisations.)</p>  <p>Vous pouvez penser qu'une fonction de rendu des éléments reçoit simplement un élément de la source de données du contrôle ListView. Qu'elle crée ensuite les composants HTML nécessaires à cet élément en particulier et renvoie le composant racine que le contrôle ListView peut ajouter au DOM. C'est essentiellement ce qui se passe, mais vous devez prendre en considération deux points complémentaires. D'abord, comme les données de l'élément même peuvent être chargées de manière asynchrone, il est logique de lier la création des composants à la disponibilité de ces données. Ensuite, le processus de rendu de l'élément même peut entraîner d'autres tâches asynchrones, telles que le chargement d'images à partir d'URI à distance ou la lecture de données dans d'autres fichiers identifiés dans les données de l'élément. Les différents niveaux d'optimisation que nous allons voir, en fait, peuvent donner lieu à un nombre arbitraire de tâches asynchrones entre la demande des composants de l'élément et la distribution effective de ces composants.</p>  <p>Ici encore, vous pouvez donc vous attendre à voir apparaître des promesses ! D'abord, le contrôle ListView ne communique pas simplement les données de l'élément au convertisseur directement ; il fournit une promesse concernant ces données. Et la fonction ne renvoie pas directement le composant racine de l'élément ; elle renvoie une promesse concernant ce composant. Ceci permet au contrôle ListView d'associer plusieurs promesses de rendu d'éléments et d'attendre (en mode asynchrone) qu'une page entière d'éléments soit rendue. En fait, il procède ainsi pour gérer intelligemment l'élaboration de différentes pages, en créant d'abord la page des éléments visibles, puis deux pages hors écran avant et après (les deux pages que les utilisateurs ont le plus de chances de consulter ensuite). En outre, la mise en place de toutes ces promesses signifie que le contrôle ListView peut facilement annuler le rendu des éléments non terminés si l'utilisateur s'éloigne, ce qui évite de créer inutilement des composants.</p>  <p>Nous pouvons voir comment ces promesses sont utilisées dans la fonction <b>simpleRenderer</b> de l'exemple :</p>  <p> </p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> simpleRenderer(itemPromise) {<br />    <span style="color: rgb(0, 0, 255);">return</span> itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />        <span style="color: rgb(0, 0, 255);">var</span> element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />        element.className = <span style="color: rgb(0, 96, 128);">&quot;itemTempl&quot;</span>;<br />        element.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;&lt;img src='&quot;</span> + item.data.thumbnail +<br />            <span style="color: rgb(0, 96, 128);">&quot;' alt='Databound image' /&gt;&lt;div class='content'&gt;&quot;</span> + item.data.title + <span style="color: rgb(0, 96, 128);">&quot;&lt;/div&gt;&quot;</span>;<br />        <span style="color: rgb(0, 0, 255);">return</span> element;<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>Ce code associe d'abord un gestionnaire Terminé à <b>itemPromise</b>. Le gestionnaire est appelé lorsque les données de l'élément sont disponibles et répond en créant les composants. Mais remarquez à nouveau que nous ne renvoyons pas l'élément directement : nous renvoyons une promesse qui est réalisée avec ce composant. En d'autres termes, la valeur renvoyée par <b>itemPromise.then()</b> est une promesse qui est réalisée avec <i>element </i>si et quand le contrôle ListView en a besoin.</p>

<p>Le renvoi d'une promesse nous permet d'effectuer d'autres tâches de synchronisation si nécessaire. Dans ce cas, le convertisseur peut simplement relier ces promesses intermédiaires et renvoyer la promesse issue du dernier appel de la méthode <b>then</b> dans la chaîne. Par exemple :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> someRenderer(itemPromise) {<br />    <span style="color: rgb(0, 0, 255);">return</span> itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />        <span style="color: rgb(0, 0, 255);">return</span> doSomeWorkAsync(item.data);<br />    }).then(<span style="color: rgb(0, 0, 255);">function</span> (results) {<br />        <span style="color: rgb(0, 0, 255);">return</span> doMoreWorkAsync(results1);<br />    }).then(<span style="color: rgb(0, 0, 255);">function</span> (results2) {<br />        <span style="color: rgb(0, 0, 255);">var</span> element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />        <span style="color: rgb(0, 128, 0);">// use results2 to configure the element</span><br />        <span style="color: rgb(0, 0, 255);">return</span> element;<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>Notez que dans ce cas, nous n'utilisons <i>pas</i> <b>done</b> à la fin de la chaîne, car nous renvoyons la promesse issue du dernier appel de la méthode <b>then</b>. Le contrôle ListView est chargé de la gestion des erreurs susceptibles de survenir.</p>

<h2>Convertisseurs d'espaces réservés</h2>

<p>La prochaine étape d'optimisation ListView utilise un <i>convertisseur d'espace réservé</i> qui décompose la création du composant en deux phases. Cela permet au contrôle ListView de demander uniquement les parties d'un composant qui sont nécessaires pour définir la disposition globale de la liste, sans créer tous les composants à l'intérieur de chaque élément. Le contrôle ListView peut ainsi s'acquitter de sa passe de disposition rapidement tout en demeurant hautement réactif aux saisies. Il peut ensuite demander le reste du composant plus tard.</p>

<p>Un convertisseur d'espace réservé renvoie un objet avec deux propriétés au lieu d'une simple promesse :</p>

<ul>
  <li><i>element</i> Composant de niveau supérieur dans la structure de l'élément qui permet de définir sa taille et sa forme et ne dépend pas des données de l'élément.</li>

  <li><i>renderComplete</i> Promesse qui est réalisée lorsque le reste du contenu du composant est créé. En d'autres termes, cette propriété renvoie la promesse à partir de la chaîne que vous avez démarrée avec <b>itemPromise.then</b> comme dans l'exemple précédent.</li>
</ul>

<p>Le contrôle ListView est suffisamment intelligent pour savoir si votre convertisseur renvoie une promesse (cas élémentaire de l'exemple précédent) ou un objet avec les propriétés <i>element</i> et <i>renderComplete</i> (cas plus avancés). Ainsi, le convertisseur d'espace réservé équivalent (dans l'exemple) pour la fonction <b>simpleRenderer</b> précédente ressemble à ceci :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> placeholderRenderer(itemPromise) {<br />    <span style="color: rgb(0, 128, 0);">// create a basic template for the item that doesn't depend on the data</span><br />    <span style="color: rgb(0, 0, 255);">var</span> element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />    element.className = <span style="color: rgb(0, 96, 128);">&quot;itemTempl&quot;</span>;<br />    element.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;&lt;div class='content'&gt;...&lt;/div&gt;&quot;</span>;<br /><br />    <span style="color: rgb(0, 128, 0);">// return the element as the placeholder, and a callback to update it when data is available</span><br />    <span style="color: rgb(0, 0, 255);">return</span> {<br />        element: element,<br /><br />        <span style="color: rgb(0, 128, 0);">// specifies a promise that will be completed when rendering is complete</span><br />        <span style="color: rgb(0, 128, 0);">// itemPromise will complete when the data is available</span><br />        renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />            <span style="color: rgb(0, 128, 0);">// mutate the element to include the data</span><br />            element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>).innerText = item.data.title;<br />            element.insertAdjacentHTML(<span style="color: rgb(0, 96, 128);">&quot;afterBegin&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;&lt;img src='&quot;</span> +<br />                item.data.thumbnail + <span style="color: rgb(0, 96, 128);">&quot;' alt='Databound image' /&gt;&quot;</span>);<br />        })<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Notez que l'affectation <i>element.innerHTML</i> peut être déplacée à l'intérieur de <b>renderComplete</b>, car la classe <i>itemTempl</i> dans le fichier css/scenario1.css de l'exemple stipule directement la largeur et la hauteur de l'élément. L'affectation est incluse dans la propriété <i>element</i>, car elle fournit le texte « … » par défaut dans l'espace réservé. Il serait également possible d'utiliser un composant <i>img</i> se rapportant à une petite ressource dans le package qui est partagée dans tous les éléments (et dont le rendu est par conséquent rapide).</p>

<h2>Convertisseurs d'espaces réservés de recyclage</h2>

<p>La prochaine optimisation, le convertisseur <i>d'espace réservé de recyclage</i>, n'apporte aucune nouveauté sur le front des promesses. Elle met en revanche l'accent sur un deuxième paramètre du convertisseur, nommé <i>recycled</i>. Il s'agit du composant racine d'un élément qui a déjà été rendu mais qui n'est plus visible. Ainsi, les composants enfants du composant « recycled » (recyclé) sont déjà en place et vous pouvez simplement remplacer les données et même transformer certains de ces composants. Ceci évite la plupart des coûteux appels de création de composants qui sont nécessaires pour créer un élément entièrement nouveau et permet d'accélérer le processus de rendu.</p>

<p>Le contrôle ListView peut fournir un composant « recycled » lorsque sa propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211835.aspx" target="_blank">loadingBehavior</a><b></b> est définie sur « randomaccess ». Si le composant <i>recycled</i> est stipulé, vous pouvez simplement supprimer les données du composant (et ses enfants), le renvoyer comme espace réservé, puis indiquer d'autres données et créer des enfants supplémentaires (le cas échéant) dans <i>renderComplete</i>. Si aucun composant « recycled » n'est fourni (par exemple si le contrôle ListView est créé en premier ou si <b>loadingBehavior</b> est « incrémentiel »), vous devez créer entièrement le composant. Voici le code de l'exemple correspondant à cette variante :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> recyclingPlaceholderRenderer(itemPromise, recycled) {<br />    <span style="color: rgb(0, 0, 255);">var</span> element, img, label;<br />    <span style="color: rgb(0, 0, 255);">if</span> (!recycled) {<br />        <span style="color: rgb(0, 128, 0);">// create a basic template for the item that doesn't depend on the data</span><br />        element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />        element.className = <span style="color: rgb(0, 96, 128);">&quot;itemTempl&quot;</span>;<br />        element.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;&lt;img alt='Databound image' style='visibility:hidden;'/&gt;&quot;</span> +<br />            <span style="color: rgb(0, 96, 128);">&quot;&lt;div class='content'&gt;...&lt;/div&gt;&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// clean up the recycled element so that we can reuse it </span><br />        element = recycled;<br />        label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>);<br />        label.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;...&quot;</span>;<br />        img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>);<br />        img.style.visibility = <span style="color: rgb(0, 96, 128);">&quot;hidden&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">return</span> {<br />        element: element,<br />        renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />            <span style="color: rgb(0, 128, 0);">// mutate the element to include the data</span><br />            <span style="color: rgb(0, 0, 255);">if</span> (!label) {<br />                label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>);<br />                img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>);<br />            }<br />            label.innerText = item.data.title;<br />            img.src = item.data.thumbnail;<br />            img.style.visibility = <span style="color: rgb(0, 96, 128);">&quot;visible&quot;</span>;<br />        })<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Dans <i>renderComplete</i>, veillez à vérifier l'existence des composants que vous ne créez pas pour un nouvel espace réservé (par exemple <i>label</i>) et créez-les si cela est nécessaire.</p>

<p>Si vous souhaitez supprimer les éléments recyclés de manière plus générale, notez que vous pouvez attribuer une fonction à la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211846.aspx" target="_blank">resetItem</a><b></b> du contrôle ListView. Le code de cette fonction serait alors similaire à celui présenté ci-dessus. Il en va de même pour la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh700726.aspx" target="_blank">resetGroupHeader</a><b></b>, car vous pouvez utiliser les fonctions de modèles pour les en-têtes de groupes comme pour les éléments. Nous en avons peu parlé, car les en-têtes de groupes sont beaucoup moins nombreux et les implications en termes de performances ne sont généralement pas les mêmes. La fonctionnalité existe néanmoins.</p>

<h2>Convertisseurs à plusieurs phases</h2>

<p>Tout ceci nous amène à l'avant-dernière optimisation, le <i>convertisseur à plusieurs phases</i>. Il prolonge le convertisseur d'espace réservé de recyclage aux images et autres données multimédias à chargement différé tant que le reste de l'élément n'est pas entièrement présent dans le DOM. Il retarde également des effets, tels que les animations, tant que l'élément n'est pas réellement à l'écran. Les utilisateurs se déplaçant souvent très rapidement au sein du contrôle ListView, il est logique de reporter de manière asynchrone les opérations les plus exigeantes jusqu'à ce que le contrôle parvienne à une position stable.</p>

<p>Le contrôle ListView offre les points de raccordement nécessaires lorsque les membres de <b>item</b> sont issus de <b>itemPromise</b> : une propriété nommée <b>ready</b> (une promesse) et deux méthodes, <b>loadImage</b> et <b>isOnScreen</b>, toutes les deux renvoyant plus de promesses. C'est-à-dire :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// item.ready, item.loadImage, and item.isOnScreen available</span><br />})<br /></pre>
  </div>
</blockquote>

<p>Voici comment les utiliser :</p>

<ul>
  <li><b>ready</b> Renvoie cette promesse à partir du premier gestionnaire Terminé de votre chaîne. Cette promesse est réalisée lorsque l'intégralité de la structure du composant a été rendue et est visible. Cela signifie que vous pouvez associer une autre méthode <b>then</b> à un gestionnaire Terminé dans lequel vous effectuez d'autres tâches postérieures à la visibilité, par exemple le chargement d'images.</li>

  <li><b>loadImage</b> Télécharge une image à partir d'un URI et l'affiche dans le composant <i>img</i> donné, ce qui renvoie une promesse qui est réalisée avec ce même composant. Vous joignez un gestionnaire Terminé à cette promesse, qui renvoie à son tour la promesse depuis <b>isOnScreen</b>. Notez que <b>loadImage</b> crée un composant <i>img</i> si aucun n'est fourni et le distribue à votre gestionnaire Terminé.</li>

  <li><b>isOnScreen</b> Renvoie une promesse dont la valeur de réalisation est une valeur booléenne qui indique si le composant est visible ou non. Dans les implémentations actuelles, il s'agit d'une valeur connue et la promesse est donc réalisée de manière synchrone. En l'incluant dans une promesse, cependant, elle peut être utilisée dans une chaîne plus longue.</li>
</ul>

<p>Tout cela est illustré dans la fonction <b>multistageRenderer</b> de l'exemple, où la fin du chargement de l'image déclenche l'apparition en fondu d'une animation. Voici simplement ce qui est renvoyé par la promesse <i>renderComplete</i> :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// mutate the element to update only the title</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!label) { label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>); }<br />    label.innerText = item.data.title;<br /><br />    <span style="color: rgb(0, 128, 0);">// use the item.ready promise to delay the more expensive work</span><br />    <span style="color: rgb(0, 0, 255);">return</span> item.ready;<br />    <span style="color: rgb(0, 128, 0);">// use the ability to chain promises, to enable work to be cancelled</span><br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// use the image loader to queue the loading of the image</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!img) { img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>); }<br />    <span style="color: rgb(0, 0, 255);">return</span> item.loadImage(item.data.thumbnail, img).then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />        <span style="color: rgb(0, 128, 0);">// once loaded check if the item is visible</span><br />        <span style="color: rgb(0, 0, 255);">return</span> item.isOnScreen();<br />    });<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (onscreen) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (!onscreen) {<br />        <span style="color: rgb(0, 128, 0);">// if the item is not visible, don't animate its opacity</span><br />        img.style.opacity = 1;<br />    } <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// if the item is visible, animate the opacity of the image</span><br />        WinJS.UI.Animation.fadeIn(img);<br />    }<br />})<br /></pre>
  </div>
</blockquote>

<p>Même si un grand nombre d'opérations se déroulent, cette chaîne de promesses demeure élémentaire. La première opération asynchrone du convertisseur actualise les parties simples de la structure des composants de l'élément, par exemple le texte. Elle renvoie ensuite la promesse dans <b>item.ready</b>. Une fois cette promesse réalisée (ou, plus précisément, si cette promesse est réalisée), nous utilisons la méthode asynchrone <b>loadImage</b> de l'élément pour déclencher le téléchargement d'une image, ce qui renvoie la promesse <b>item.isOnScreen</b> depuis ce gestionnaire Terminé. Cela signifie que l'indicateur de visibilité <i>onscreen</i> est transmis au gestionnaire Terminé final de la chaîne. Lorsque (et si) cette promesse <b>isOnScreen</b> est réalisée (ce qui signifie que l'élément est réellement visible), nous pouvons effectuer les opérations appropriées, telles que des animations.</p>

<p>Je tiens à souligner le caractère hypothétique (avec le terme « si »), car il est à nouveau probable que l'utilisateur se déplace au sein du contrôle ListView pendant le déroulement de toutes ces opérations. L'enchaînement de toutes ces promesses permet au contrôle ListView d'annuler les opérations asynchrones lorsque ces éléments sont déplacés hors de l'écran et/ou hors des pages mises en mémoire tampon. Qu'il suffise de dire que le contrôle ListView a subi à un <i>grand</i> nombre de tests de performances !</p>

<p>Il est également important de se rappeler que nous utilisons la méthode <b>then</b> dans toutes ces chaînes, car nous renvoyons toujours une promesse depuis la fonction de rendu au sein de la propriété <i>renderComplete</i>. Nous ne sommes jamais à la fin de la chaîne dans ces convertisseurs et nous n'utiliserons donc jamais <b>done</b> à la fin.</p>

<h2>Traitement de miniatures par lot</h2>

<p>La dernière optimisation constitue sans aucun doute le <i>coup de grâce</i> pour le contrôle ListView. Dans la fonction nommée <b>batchRenderer</b>, nous trouvons cette structure pour <i>renderComplete</i> (la plupart du code est omis) :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// mutate the element to update only the title</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!label) { label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>); }<br />    label.innerText = item.data.title;<br /><br />    <span style="color: rgb(0, 128, 0);">// use the item.ready promise to delay the more expensive work</span><br />    <span style="color: rgb(0, 0, 255);">return</span> item.ready;<br />    <span style="color: rgb(0, 128, 0);">// use the ability to chain promises, to enable work to be cancelled</span><br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// use the image loader to queue the loading of the image</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!img) { img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>); }<br />    <span style="color: rgb(0, 0, 255);">return</span> item.loadImage(item.data.thumbnail, img).then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />        <span style="color: rgb(0, 128, 0);">// once loaded check if the item is visible</span><br />        <span style="color: rgb(0, 0, 255);">return</span> item.isOnScreen();<br />    });<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (onscreen) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (!onscreen) {<br />        <span style="color: rgb(0, 128, 0);">// if the item is not visible, don't animate its opacity</span><br />        img.style.opacity = 1;<br />    } <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// if the item is visible, animate the opacity of the image</span><br />        WinJS.UI.Animation.fadeIn(img);<br />    }<br />})<br /></pre>
  </div>
</blockquote>

<p>Cela ressemble beaucoup à la fonction <b>multistageRenderer</b>, à l'exception de l'insertion de cet appel mystérieux destiné à la fonction <b>thumbnailBatch</b> entre l'appel <b>item.loadImage</b> et la vérification <b>item.isOnScreen</b>. La position de <b>thumbnailBatch</b> dans la chaîne indique que la valeur renvoyée doit être un gestionnaire Terminé qui renvoie lui-même une autre promesse.</p>

<p>Ce n'est pas très clair ? Nous y reviendrons en détail ! Mais d'abord, nous avons besoin d'informations complémentaires sur ce que nous tentons d'accomplir.</p>

<p>Si nous n'avions qu'un contrôle ListView avec un seul élément, les différentes optimisations de chargement ne seraient pas significatives. Mais le contrôle ListView comporte généralement de nombreux éléments et la fonction de rendu est appelée pour chacun d'entre eux. Dans la fonction <b>multistageRenderer</b> de la section précédente, le rendu de chaque élément déclenche une opération <b>item.loadImage</b> asynchrone qui télécharge sa miniature à partir d'un URI arbitraire. La durée de chaque opération peut être arbitraire. Ainsi, pour toute la liste, plusieurs appels <b>loadImage</b> peuvent se dérouler simultanément, avec le rendu de chaque élément attendant la fin de sa miniature en particulier. Jusque là, tout va bien.</p>

<p>Une des caractéristiques importantes qui n'est pas du tout visible dans la fonction <b>multistageRenderer</b>, cependant, est que le composant <i>img</i> de la miniature est <i>déjà</i> présent dans le DOM et que la fonction <b>loadImage</b> définit l'attribut <i>src</i> de cette image dès la fin du téléchargement. Ceci déclenche à son tour une mise à jour dans le moteur de rendu dès que nous revenons du reste de la chaîne de promesses, qui est essentiellement synchrone au-delà de ce point.</p>

<p>Il est alors possible que certaines des miniatures réintègrent rapidement le thread d'interface utilisateur. Ceci entraînera une trop grande évolution dans le moteur de rendu et des performances visuelles médiocres. Pour éviter cette situation, nous voulons créer entièrement ces composants <i>img</i> <i>avant</i> qu'ils ne soient dans le DOM, puis les ajouter par lots afin qu''ils soient tous gérés au cours d'une passe de rendu unique.</p>

<p>L'exemple effectue ces opérations à l'aide de la fonction <b>createBatch</b>. La fonction <b>createBatch</b> est appelée une seule fois pour toute l'application et son résultat (une autre fonction) est stocké dans la variable nommée <b>thumbnailBatch</b>:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> thumbnailBatch;<br />thumbnailBatch = createBatch();<br /></pre>
  </div>
</blockquote>

<p>Un appel à cette fonction <b>thumbnailBatch</b>, comme je vais désormais la désigner, est à nouveau inséré dans la chaîne de promesses du convertisseur. L'objectif de cette insertion, étant donné la nature du code de traitement par lot que nous examinerons plus loin, est de regrouper un ensemble de composants <i>img</i> chargés, en les libérant pour d'autres traitements à intervalles appropriés. Ici encore, en regardant simplement la chaîne de promesses dans le convertisseur, un appel à <b>thumbnailBatch()</b> doit renvoyer une fonction de gestionnaire Terminé qui renvoie une promesse et la valeur de réalisation de cette promesse (en regardant la prochaine étape de la chaîne) doit être un composant <i>img</i> qui peut ensuite être ajouté au DOM. En ajoutant ces images au DOM <i>après</i> le traitement par lot, nous associons l'intégralité du groupe dans la même passe de rendu.</p>

<p>Cette différence entre la fonction <b>batchRenderer</b> et la fonction <b>multistageRenderer</b> de la section précédente est importante : dans la deuxième fonction, le composant <i>img</i> de la miniature existe déjà dans le DOM et est transmis à la méthode <b>loadImage</b> comme deuxième paramètre. Ainsi, lorsque la méthode <b>loadImage</b> définit l'attribut <i>src</i> de l'image, le rendu est mis à jour. Au sein de la fonction <b>batchRenderer</b> toutefois, ce composant <i>img</i> est créé séparément dans la méthode <b>loadImage</b> (où l'attribut <i>src</i> est également défini), mais le composant <i>img</i> n'est pas encore présent dans le DOM. Il n'est ajouté au DOM qu'à la fin de l'étape <b>thumbnailBatch</b>, ce qui lui permet de faire partie d'un groupe au sein de cette passe de disposition unique.</p>

<p>Examinons maintenant le fonctionnement de ce traitement par lot. Voici la fonction <b>createBatch</b> dans son intégralité :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> createBatch(waitPeriod) {<br />    <span style="color: rgb(0, 0, 255);">var</span> batchTimeout = WinJS.Promise.<span style="color: rgb(0, 0, 255);">as</span>();<br />    <span style="color: rgb(0, 0, 255);">var</span> batchedItems = [];<br /><br />    <span style="color: rgb(0, 0, 255);">function</span> completeBatch() {<br />        <span style="color: rgb(0, 0, 255);">var</span> callbacks = batchedItems;<br />        batchedItems = [];<br />        <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = 0; i &lt; callbacks.length; i++) {<br />            callbacks[i]();<br />        }<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> () {<br />        batchTimeout.cancel();<br />        batchTimeout = WinJS.Promise.timeout(waitPeriod || 64).then(completeBatch);<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> delayedPromise = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (c) {<br />            batchedItems.push(c);<br />        });<br /><br />        <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> (v) {<br />            <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />                <span style="color: rgb(0, 0, 255);">return</span> v;<br />            });<br />        };<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Ici encore, la fonction <b>createBatch</b> est appelée <i>une seule fois</i> et son résultat <b>thumbnailBatch</b> est appelé pour <i>chaque </i>élément rendu<i> </i>dans la liste. Le gestionnaire Terminé que <b>thumbnailBatch</b> génère est ensuite appelé dès qu'une opération <b>loadImage</b> se termine.</p>

<p>Ce gestionnaire Terminé aurait pu être inséré directement dans la fonction de rendu, mais nous essayons dans ce cas de coordonner les activités <i>sur plusieurs éléments </i>à la fois, et non élément par élément. Cette coordination est possible grâce aux deux variables créées et initialisées au début de la fonction <b>createBatch</b> : <i>batchedTimeout</i>, initialisée en tant que promesse vide, et <i>batchedItems</i>, initialisée en tant que tableau de fonctions vide à l'origine. <b>createBatch</b> déclare également une fonction, <b>completeBatch</b>, qui vide simplement <i>batchedItems</i>, en appelant chaque fonction du tableau :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> createBatch(waitPeriod) {<br />    <span style="color: rgb(0, 0, 255);">var</span> batchTimeout = WinJS.Promise.<span style="color: rgb(0, 0, 255);">as</span>();<br />    <span style="color: rgb(0, 0, 255);">var</span> batchedItems = [];<br /><br />    <span style="color: rgb(0, 0, 255);">function</span> completeBatch() {<br />        <span style="color: rgb(0, 0, 255);">var</span> callbacks = batchedItems;<br />        batchedItems = [];<br />        <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = 0; i &lt; callbacks.length; i++) {<br />            callbacks[i]();<br />        }<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> () {<br />        batchTimeout.cancel();<br />        batchTimeout = WinJS.Promise.timeout(waitPeriod || 64).then(completeBatch);<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> delayedPromise = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (c) {<br />            batchedItems.push(c);<br />        });<br /><br />        <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> (v) {<br />            <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />                <span style="color: rgb(0, 0, 255);">return</span> v;<br />            });<br />        };<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Étudions maintenant ce qui se passe dans <b>thumbnailBatch</b> (la fonction renvoyée par <b>createBatch</b>), qui est à nouveau appelée pour chaque élément rendu. D'abord, nous <i>annulons</i> les variables <i>batchedTimeout</i> existantes et en recréons une immédiatement :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">batchTimeout<span style="color: rgb(255, 0, 0);">.</span>cancel();<br />        batchTimeout = WinJS<span style="color: rgb(255, 0, 0);">.</span>Promise<span style="color: rgb(255, 0, 0);">.</span>timeout(waitPeriod || 64)<span style="color: rgb(255, 0, 0);">.</span>then(completeBatch);<br /></pre>
  </div>
</blockquote>

<p>La deuxième ligne illustre le futur modèle de distribution/réalisation abordé dans le billet Tout sur les promesses &lt;TODO: link>: elle demande d'appeler <b>completeBatch</b> après un délai de <i>waitPeriod</i> millisecondes (avec une valeur par défaut de 64 ms). Cela signifie que tant que la fonction <b>thumbnailBatch</b> est rappelée dans un intervalle de <i>waitPeriod</i> par rapport à un appel précédent, la variable <b>batchTimeout</b> est réinitialisée sur un autre délai <i>waitPeriod</i>. Et comme la fonction <b>thumbnailBatch</b> est appelée uniquement <i>après </i>la fin d'un appel <b>item.loadImage</b>, cela revient à dire que les opérations <b>loadImage</b> qui se terminent dans l'intervalle <i>waitPeriod</i> par rapport à la précédente seront incluses dans le même lot. Lorsque l'intervalle est supérieur à <i>waitPeriod</i>, le lot est traité (les images sont ajoutées au DOM) et le prochain lot commence.</p>

<p>Une fois ces délais d'expiration gérés, la fonction <b>thumbnailBatch</b> crée une nouvelle promesse qui charge simplement la fonction de répartiteur complète dans le tableau <i>batchedItems</i> :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> delayedPromise = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (c) {<br />         batchedItems.push(c);<br />     });<br /></pre>
  </div>
</blockquote>

<p>Comme l'indique le billet Tout sur les promesses &lt;TODO: link> n'oubliez pas qu'une promesse n'est ni plus ni moins qu'une construction de code, et c'est tout ce que nous avons ici. La promesse qui vient d'être créée n'est associée à aucun comportement asynchrone : nous ajoutons simplement la fonction de répartiteur complète <i>c</i> dans <i>batchedItems</i>. Il est évident toutefois que nous ne touchons pas au répartiteur tant que la fonction <i>batchedTimeout</i> n'est pas terminée de manière asynchrone. Il existe par conséquent une relation asynchrone dans ce cas. Lorsque le délai d'expiration se produit et que nous effaçons le lot (à l'intérieur de <b>completeBatch</b>), nous appelons les gestionnaires Terminé qui sont indiqués ailleurs dans <b>delayedPromise.then</b>.</p>

<p>Ceci nous amène aux dernières lignes de code dans <b>createBatch</b>, qui est la fonction que <b>thumbnailBatch</b> renvoie réellement. Cette fonction est exactement le gestionnaire Terminé qui est inséré dans l'intégralité de la chaîne de promesses du convertisseur.</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> (v) {<br />           <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />               <span style="color: rgb(0, 0, 255);">return</span> v;<br />           });<br />       };<br /></pre>
  </div>
</blockquote>

<p>En fait, insérons ce code directement dans la chaîne de promesses pour voir les relations que nous obtenons :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">return</span> item.loadImage(item.data.thumbnail);<br />          }).then(<span style="color: rgb(0, 0, 255);">function</span> (v) {<br />              <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />                  <span style="color: rgb(0, 0, 255);">return</span> v;<br />              });<br />          ).then(<span style="color: rgb(0, 0, 255);">function</span> (newimg) {<br /></pre>
  </div>
</blockquote>

<p>Nous voyons maintenant que l'argument <i>v</i> est le résultat de <b>item.loadImage</b>, qui est le composant <i>img</i> créé à notre intention. Si nous ne voulions pas du traitement par lot, nous pourrions simplement indiquer <b>return WinJS.Promise.as(v)</b> et toute la chaîne fonctionnerait parfaitement : <i>v</i> serait dans ce cas transmis de manière synchrone et apparaîtrait comme <i>newimg</i> à la prochaine étape.</p>

<p>Nous renvoyons toutefois à la place une promesse depuis <b>delayedPromise.then</b> qui ne sera pas réalisée (avec <i>v</i>) tant que la fonction <i>batchedTimeout</i> n'est pas réalisée. À ce stade (lorsqu'un délai de <i>waitPeriod</i> sépare la fin des opérations <b>loadImage</b>), ces composants <i>img</i> sont ensuite distribués à la prochaine étape de la chaîne, où ils sont ajoutés au DOM.</p>

<p>Et c'est tout !</p>

<h2>Pour conclure</h2>

<p>Les cinq différentes fonctions de rendu illustrées dans l'<a href="http://code.msdn.microsoft.com/windowsapps/ListView-performance-39fb71f0" target="_blank">exemple d'optimisation des performances de contrôle HTML ListView</a> ont toutes une caractéristique en commun : elles montrent comment la relation asynchrone entre le contrôle ListView et le convertisseur (exprimée au moyen de promesses) confère au convertisseur une extrême flexibilité quant à la manière dont il produit des composants pour les éléments de la liste et quant au moment où il les produit. Pour écrire vos propres applications, la stratégie que vous utilisez pour l'optimisation du contrôle ListView dépend énormément de la taille de votre source de données, de la complexité des éléments eux-mêmes et de la quantité de données que vous obtenez de manière asynchrone pour ces éléments (téléchargement d'images distantes, par exemple). Pour de nombreuses raisons, il est souhaitable de simplifier au maximum les convertisseurs d'éléments en vue de satisfaire vos objectifs de performances. Mais dans tous les cas, vous disposez maintenant de tous les outils dont vous avez besoin pour optimiser les performances du contrôle ListView et de votre application.</p>

<p>Kraig Brockschmidt 
  <br />Chef de projet, équipe Écosystème Windows 

  <br />Auteur de <a href="http://blogs.msdn.com/b/microsoft_press/archive/2012/10/29/free-ebook-programming-windows-8-apps-with-html-css-and-javascript.aspx"><i>Programming Windows 8 Apps in HTML, CSS, and JavaScript</i></a></p>
<!-- Title: “Optimisation du rendu des éléments du contrôle ListView” Tags: “applications du Windows Store, rendu, traitement par lot, lot, rendu, convertisseur, ListView” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Participez à la manifestation « Game On Virtual Event »</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/participez-la-manifestation-game-on-virtual-event</link>
      <pubDate>Wed, 12 Jun 2013 11:32:01 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/06/12/participez-la-manifestation-game-on-virtual-event/</guid>
      <description><![CDATA[Les jeux constituent une classe d'applications primordiale dans le Windows Store. Si vous souhaitez...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Les jeux constituent une classe d'applications primordiale dans le Windows Store. Si vous souhaitez créer un jeu Windows Store, la manifestation virtuelle sur la conception des jeux peut vous aider. Cette manifestation gratuite est ouverte aux développeurs de jeux comme aux professionnels. </p>  <p>Nous utiliserons <a href="https://aka.ms/yoyogamesgamemaker" target="_blank">GameMaker : Studio</a> de YoYo Games pour vous montrer comment créer et publier plus rapidement des jeux de grande qualité. Grâce aux nombreuses options de conception intégrées et aux formidables outils de glisser-déplacer de GameMaker : Studio, vous pouvez commencer facilement, même si vous n'avez pas encore de projet bien défini ou n'avez pas encore une grande expérience en développement. Cependant, si vous êtes un développeur de jeux expérimenté, les outils avancés vous permettront d'élaborer une expérience de jeu unique. </p>  <p><a href="https://aka.ms/gameonevent"><img title="clip_image002" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8666.clip_image002_0385EAB3.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8666.clip_5F00_image002_5F00_0385EAB3.jpg" width="500" height="154" /></a></p>  <p>La manifestation en ligne commence le samedi 15 juin à 10 h 00 PDT, avec une session de lancement et une conversation en direct. Vous apprendrez à connaître les différents types de jeux et à ajouter des graphismes, des niveaux et du son aux jeux de base, tout en découvrant comment personnaliser votre propre jeu. Tout au long de la semaine, une assistance personnalisée vous sera proposée via les forums GameMaker.</p>  <p>Que vous soyez étudiant, développeur débutant ou professionnel chevronné, cette manifestation vous aidera à créer, ajouter et publier des jeux sur le Windows Store. Pour en savoir plus, vous inscrire et découvrir les ressources et outils gratuits, consultez la page <a href="http://msdnevents.com/gameon/" target="_blank">http://msdnevents.com/gameon/</a>. </p>  <p>--Robert Rodriguez-Lawson, Responsable senior de la publication de contenu, Contenu de développement Windows</p> <!-- Title: “Participez à la manifestation « Game On Virtual Event »” Tags: “jeux du Windows Store, jeux, Game on, manifestations, événements” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Stockage sécurisé des informations d'identification : votre solution pour gérer les noms d'utilisateur et les mots de passe dans votre application du Windows Store</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/stockage-scuris-des-informations-didentification-votre-solution-pour-grer-les-noms-dutilisateur-et-les-mots-de-passe-dans-votre-application-du-windows-store</link>
      <pubDate>Tue, 04 Jun 2013 19:42:01 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/06/04/stockage-scuris-des-informations-didentification-votre-solution-pour-grer-les-noms-dutilisateur-et-les-mots-de-passe-dans-votre-application-du-windows-store/</guid>
      <description><![CDATA[Si vous n'avez pas encore entendu parler du Stockage sécurisé des informations d'identification qui...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Si vous n'avez pas encore entendu parler du <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465069.aspx" target="_blank">Stockage sécurisé des informations d'identification</a> qui est disponible pour les applications du Windows Store, il est temps d'aborder le sujet. Pourquoi ? Parce que, non seulement il simplifie le <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465060.aspx" target="_blank">stockage</a> et la <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/jj839731.aspx" target="_blank">récupération des informations d'identification de l'utilisateur</a>, mais il les stocke de manière sécurisée et les informations d'identification suivent « gratuitement » les utilisateurs avec leur compte Microsoft.</p>  <p>Supposons que vous disposiez d'une application qui se connecte à un service pour accéder à des ressources protégées, telles que des fichiers multimédias, un réseau social, etc. Votre service requiert des informations de connexion pour chaque utilisateur. Vous avez donc intégré à votre application une interface utilisateur qui récupère le nom d'utilisateur et le mot de passe de l'utilisateur, qui sont ensuite utilisés pour connecter l'utilisateur au service. Tout fonctionne à merveille.</p>  <p>Vous voulez maintenant aller plus loin pour vos utilisateurs et stocker leurs informations d'identification de manière sécurisée afin qu'ils n'aient pas à se connecter à chaque fois qu'ils utilisent votre application. C'est là que le Stockage sécurisé des informations d'identification intervient. En quelques appels simples à l'API du Stockage sécurisé des informations d'identification, vous pouvez stocker le nom d'utilisateur et le mot de passe de votre utilisateur, puis les récupérer facilement et connecter l'utilisateur lors de sa prochaine ouverture de votre application.</p>  <h2>Stockage sécurisé</h2>  <p>Un des atouts du Stockage sécurisé des informations d'identification pour votre application est qu'il stocke les informations d'identification de l'utilisateur dans un lieu sécurisé et que ces informations d'identification sont chiffrées lorsqu'elles sont stockées sur le disque. Vous pourriez évidemment stocker les informations d'identification de l'utilisateur dans un fichier du stockage local de votre application, mais enregistrer ce type d'informations en texte brut présente une faille de sécurité considérable. Si le système de l'utilisateur est compromis d'une manière ou d'une autre, son nom d'utilisateur et son mot de passe sont facilement accessibles et utilisables. Si le nom d'utilisateur et le mot de passe sont stockés avec le Stockage sécurisé des informations d'identification, une source malveillante ne réussira qu'à récupérer un fichier chiffré.</p>  <p>Le Stockage sécurisé des informations d'identification est unique pour chaque utilisateur d'un PC Windows et l'accès aux informations d'identification est limité à l'application qui les a stockées. En d'autres termes, vous ne pouvez récupérer que les informations d'identification que vous avez stockées pour votre application. De même, aucune autre application ne peut obtenir les informations d'identification que votre application a stockées dans le stockage sécurisé.</p>  <h2>Informations d'identification itinérantes</h2>  <p>Autre avantage pour les utilisateurs : lorsque vous stockez leur nom d'utilisateur et leur mot de passe avec le Stockage sécurisé des informations d'identification, ces dernières suivent leur compte Microsoft sur n'importe quelle machine approuvée qu'ils utilisent avec ce compte Microsoft. Ceci rend votre application sécurisée encore plus pratique pour vos utilisateurs, car elle peut les connecter automatiquement (sans demander une nouvelle fois à l'utilisateur ses informations d'identification) sur n'importe quelle machine approuvée sur laquelle ils ont installé votre application et associé leur compte Microsoft.</p>  <p>Le fonctionnement est légèrement différent pour les comptes de domaine. Si des informations d'identification sont stockées avec votre compte Microsoft et que vous associez ce compte à un compte de domaine (par exemple le compte que vous utilisez au travail), vos informations d'identification suivent ce compte de domaine. Toutefois, les nouvelles informations d'identification ajoutées une fois que vous êtes connecté avec le compte de domaine ne sont pas itinérantes. Ceci garantit que les informations d'identification privées du domaine ne sont pas exposées à l'extérieur du domaine.</p>  <h2>Stockage des informations d'identification de l'utilisateur</h2>  <p>Le stockage des informations d'identification de l'utilisateur dans le Stockage sécurisé des informations d'identification est une procédure simple qui se décompose en deux étapes. Commencez par obtenir une référence au Stockage sécurisé des informations d'identification à l'aide de l'objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.aspx" target="_blank">PasswordVault</a> auprès de l'espace de noms <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.aspx" target="_blank">Windows.Security.Credentials</a>. Créez ensuite un objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordcredential.aspx" target="_blank">PasswordCredential</a> contenant un identifiant pour votre application, le nom d'utilisateur et le mot de passe, puis transmettez ces informations à la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh701231.aspx" target="_blank">PasswordVault.Add()</a> en vue d'ajouter les informations d'identification dans le stockage sécurisé.</p>  <p><strong>C#</strong></p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">var vault = <span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.Add(<span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: rgb(0, 96, 128);">&quot;My App&quot;</span>, username, password));<br /></pre>
  </div>
</blockquote>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> vault = <span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.add(<span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: rgb(0, 96, 128);">&quot;My App&quot;</span>, username, password));<br /></pre>
  </div>
</blockquote>

<h2>Récupération des informations d'identification de l'utilisateur</h2>

<p>Plusieurs options permettent de récupérer les informations d'identification de l'utilisateur dans le Stockage sécurisé des informations d'identification après avoir obtenu une référence à l'objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.aspx" target="_blank">PasswordVault</a>.</p>

<ul>
  <li>Vous pouvez récupérer toutes les informations d'identification que l'utilisateur a fournies pour votre application dans le Stockage sécurisé avec la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.retrieveall.aspx" target="_blank">PasswordVault.RetrieveAll()</a>.</li>

  <li>Si vous connaissez le nom d'utilisateur des informations d'identification, vous pouvez récupérer toutes les informations d'identification de ce nom d'utilisateur grâce à la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.findallbyusername.aspx" target="_blank">PasswordVault.FindAllByUserName()</a>.</li>

  <li>Si vous connaissez le nom de ressource des informations d'identification, vous pouvez récupérer toutes les informations d'identification de ce nom de ressource grâce à la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.findallbyresource.aspx" target="_blank">PasswordVault.FindAllByResource()</a>.</li>

  <li>Enfin, si vous connaissez à la fois le nom d'utilisateur et le nom de ressource d'informations d'identification en particulier, vous pouvez récupérer uniquement ces informations d'identification à l'aide de la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.retrieve.aspx" target="_blank">PasswordVault.Retrieve()</a>.</li>
</ul>

<p>Examinons un exemple dans lequel nous avons stocké globalement le nom de ressource dans une application et où nous connectons l'utilisateur automatiquement si nous trouvons des informations d'identification qui lui correspondent. Si nous trouvons plusieurs informations d'identification pour l'utilisateur, nous lui demandons de choisir les informations par défaut à utiliser lors de la connexion.</p>

<p><strong>C#</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">string</span> resourceName = <span style="color: rgb(0, 96, 128);">&quot;My App&quot;</span>;<br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">string</span> defaultUserName;<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> Login()<br />{<br />    var loginCredential = GetCredentialFromLocker();<br /><br />    <span style="color: rgb(0, 0, 255);">if</span> (loginCredential != <span style="color: rgb(0, 0, 255);">null</span>)<br />    {<br />        <span style="color: rgb(0, 128, 0);">// There is a credential stored in the locker.</span><br />        <span style="color: rgb(0, 128, 0);">// Populate the Password property of the credential</span><br />        <span style="color: rgb(0, 128, 0);">// for automatic login.</span><br />        loginCredential.RetrievePassword();<br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span><br />    {<br />        <span style="color: rgb(0, 128, 0);">// There is no credential stored in the locker.</span><br />        <span style="color: rgb(0, 128, 0);">// Display UI to get user credentials.</span><br />        loginCredential = GetLoginCredentialUI();<br />    }<br /><br />    <span style="color: rgb(0, 128, 0);">// Log the user in.</span><br />    ServerLogin(loginCredential.UserName, loginCredential.Password);<br />}<br /><br /><br /><span style="color: rgb(0, 0, 255);">private</span> Windows.Security.Credentials.PasswordCredential GetCredentialFromLocker()<br />{<br />    Windows.Security.Credentials.PasswordCredential credential = <span style="color: rgb(0, 0, 255);">null</span>;<br /><br />    var vault = <span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordVault();<br />    var credentialList = vault.FindAllByResource(resourceName);<br />    <span style="color: rgb(0, 0, 255);">if</span> (credentialList.Count &gt; 0)<br />    {<br />        <span style="color: rgb(0, 0, 255);">if</span> (credentialList.Count == 1)<br />        {<br />            credential = credentialList[0];<br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span><br />        {<br />            <span style="color: rgb(0, 128, 0);">// When there are multiple usernames,</span><br />            <span style="color: rgb(0, 128, 0);">// retrieve the default username. If one doesn’t</span><br />            <span style="color: rgb(0, 128, 0);">// exist, then display UI to have the user select</span><br />            <span style="color: rgb(0, 128, 0);">// a default username.</span><br /><br />            defaultUserName = GetDefaultUserNameUI();<br /><br />            credential = vault.Retrieve(resourceName, defaultUserName);<br />        }<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> credential;<br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>JavaScript</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> resourceName = <span style="color: rgb(0, 96, 128);">&quot;My App&quot;</span>;<br /><span style="color: rgb(0, 0, 255);">var</span> defaultUserName;<br /><br /><span style="color: rgb(0, 0, 255);">function</span> login() {<br />    <span style="color: rgb(0, 0, 255);">var</span> loginCredential = getCredentialFromLocker();<br /><br />    <span style="color: rgb(0, 0, 255);">if</span> (loginCredential != <span style="color: rgb(0, 0, 255);">null</span>) {<br />        <span style="color: rgb(0, 128, 0);">// There is a credential stored in the locker.</span><br />        <span style="color: rgb(0, 128, 0);">// Populate the Password property of the credential</span><br />        <span style="color: rgb(0, 128, 0);">// for automatic login.</span><br />        loginCredential.retrievePassword();<br />    } <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// There is no credential stored in the locker.</span><br />        <span style="color: rgb(0, 128, 0);">// Display UI to get user credentials.</span><br />        loginCredential = getLoginCredentialUI();<br />    }<br /><br />    <span style="color: rgb(0, 128, 0);">// Log the user in.</span><br />    serverLogin(loginCredential.userName, loginCredential.password);<br />}<br /><br /><br /><span style="color: rgb(0, 0, 255);">function</span> GetCredentialFromLocker() {<br />    <span style="color: rgb(0, 0, 255);">var</span> credential = <span style="color: rgb(0, 0, 255);">null</span>;<br /><br />    <span style="color: rgb(0, 0, 255);">var</span> vault = <span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordVault();<br />    <span style="color: rgb(0, 0, 255);">var</span> credentialList = vault.findAllByResource(resourceName);<br />    <span style="color: rgb(0, 0, 255);">if</span> (credentialList.length &gt; 0) {<br />        <span style="color: rgb(0, 0, 255);">if</span> (credentialList.length == 1) {<br />            credential = credentialList[0];<br />        } <span style="color: rgb(0, 0, 255);">else</span> {<br />            <span style="color: rgb(0, 128, 0);">// When there are multiple usernames,</span><br />            <span style="color: rgb(0, 128, 0);">// retrieve the default username. If one doesn’t</span><br />            <span style="color: rgb(0, 128, 0);">// exist, display UI to have the user select</span><br />            <span style="color: rgb(0, 128, 0);">// a default username.</span><br /><br />            defaultUserName = getDefaultUserNameUI();<br />            credential = vault.retrieve(resourceName, defaultUserName);<br />        }<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> credential;<br />}<br /></pre>
  </div>
</blockquote>

<h2>Suppression des informations d'identification de l'utilisateur</h2>

<p>La suppression des informations d'identification de l'utilisateur dans le Stockage sécurisé des informations d'identification est également une procédure simple qui se décompose en deux étapes. Cette fois encore, obtenez une référence au Stockage sécurisé des informations d'identification à l'aide de l'objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.passwordvault.aspx" target="_blank">PasswordVault</a> auprès de l'espace de noms <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.aspx" target="_blank">Windows.Security.Credentials</a>. Ensuite, transmettez les informations d'identification que vous souhaitez supprimer à la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh701242.aspx" target="_blank">PasswordVault.Remove()</a>.</p>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">var vault = <span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.Remove(<span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: rgb(0, 96, 128);">&quot;My App&quot;</span>, username, password));<br /></pre>
  </div>
</blockquote>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> vault = <span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.remove(<span style="color: rgb(0, 0, 255);">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: rgb(0, 96, 128);">&quot;My App&quot;</span>, username, password));<br /></pre>
  </div>
</blockquote>

<h2>Simplicité et sécurité</h2>

<p>Comme vous pouvez le voir, le Stockage sécurisé des informations d'identification est une fonctionnalité facile à utiliser qui simplifie l'authentification des utilisateurs et le stockage des informations d'identification de ces utilisateurs pour une utilisation future, tout cela dans un mode hautement sécurisé.</p>

<p>Les autres rubriques concernant l'authentification des applications Windows 8 sont notamment celles sur le <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465281.aspx" target="_blank">service Broker d'authentification Web</a>, qui permet de récupérer un jeton d'authentification auprès d'un site Web (par exemple, OAuth) et celle sur la <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh770853.aspx" target="_blank">personnalisation de votre applications en fonction du compte Microsoft d'un utilisateur</a>.</p>

<p>Pour plus d'informations, consultez</p>

<ul>
  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211367.aspx" target="_blank">Gestion des informations utilisateur (JavaScript)</a></li>

  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/xaml/BR229572(v=win.10).aspx" target="_blank">Gestion des informations utilisateur (applications du Windows Store en C#/VB/C++ et XAML)</a></li>

  <li><a href="http://code.msdn.microsoft.com/windowsapps/PasswordVault-f01be74a" target="_blank">Exemple de Stockage sécurisé des informations d'identification</a></li>

  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.security.credentials.aspx" target="_blank">Windows.Security.Credentials</a></li>
</ul>

<p><i></i></p>

<p>--Doug Rothaus, Développeur de contenu, Contenu de développement Windows</p>

<p>Remerciements tout particuliers à Yashar Bahman pour son aide et sa participation à ce billet.</p>
<!-- Title: “Stockage sécurisé des informations d'identification : votre solution pour gérer les noms d'utilisateur et les mots de passe dans votre application du Windows Store” Tags: “récupération des informations d'identification, stockage des informations d'identification, stockage sécurisé, Stockage sécurisé des informations d'identification” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Créer des applications prenant en charge la localisation avec la géolocalisation et l'application Cartes Bing</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/crer-des-applications-prenant-en-charge-la-localisation-avec-la-golocalisation-et-lapplication-cartes-bing</link>
      <pubDate>Tue, 28 May 2013 11:03:13 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/05/28/crer-des-applications-prenant-en-charge-la-localisation-avec-la-golocalisation-et-lapplication-cartes-bing/</guid>
      <description><![CDATA[En associant la localisation d'un utilisateur à la logique métier de votre application, vous pouvez...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>En associant la localisation d'un utilisateur à la logique métier de votre application, vous pouvez facilement fournir aux utilisateurs de l'application la météo, les bons de réduction, les événements sportifs ou les concerts correspondant à leur position géographique actuelle. Vous pouvez utiliser les fonctionnalités de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229921.aspx" target="_blank">géolocalisation</a> de Windows 8, ainsi que le SDK Cartes Bing, pour créer de formidables <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465148.aspx" target="_blank">applications du Windows Store prenant en charge la géolocalisation</a>.</p>  <p>Examinons comment votre application peut tirer parti du <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br225603.aspx" target="_blank">service de localisation</a> pour offrir aux utilisateurs des informations spécifiques à une localisation à l'aide d'une adresse IP, d'un réseau Wi-Fi ou de données GPS. Une fois que vous connaissez la localisation, vous pouvez utiliser le SDK Cartes Bing pour afficher la position géographique à l'utilisateur. </p>  <h2>Récupération de la localisation</h2>  <p>L'espace de noms <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.devices.geolocation.aspx">Windows.Devices.Geolocation</a> permet de récupérer votre localisation. Le fait que vous utilisiez le GPS, un réseau Wi-Fi ou une adresse IP pour récupérer la localisation d'un utilisateur dépend de deux facteurs principaux :</p>  <ol>   <li>Le niveau de précision demandé. Il s'agit du niveau de précision idéal pour répondre aux besoins de votre application. </li>    <li>La disponibilité des données de localisation. Tous les périphériques n'ont pas de GPS intégré. Il est également possible qu'aucun réseau ou qu'aucune connexion Wi-Fi ne soit disponible au moment où la localisation est demandée.</li> </ol>  <h3><a>Précision voulue</a></h3>  <p>Lors de la demande d'une localisation, votre application doit spécifier la <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx" target="_blank">précision voulue</a> afin que les données de localisation puissent être renvoyées aussi rapidement que possible dans la plage donnée. Chacun des types de localisation dispose de degrés de précision :</p>  <ul>   <li><a href="http://fr.wikipedia.org/wiki/Gps" target="_blank">GPS</a> : le GPS offre une précision optimale, jusqu'à 10 mètres environ. Toutefois, si le capteur doit « se réveiller » et acquérir les données satellite, puis trianguler les données, le renvoi des détails de localisation peut nécessiter une ou deux minutes. Cependant, une fois que le GPS a acquis les connexions satellite, il peut ensuite acquérir le point de localisation suivant plus rapidement. Évidemment, plus le GPS est utilisé et plus sa consommation énergétique est élevée. La propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx" target="_blank">Geolocator.DesiredAccuracy</a> doit être définie sur High (élevée) pour que le GPS puisse acquérir des données.</li>    <li><a href="http://fr.wikipedia.org/wiki/Wi-Fi" target="_blank">Wi-Fi</a> : une connexion Wi-Fi peut fournir une précision comprise entre 300 et 500 mètres. En cas de connexion, le renvoi des données de localisation peut être plus rapide que l'acquisition des connexions satellite par un GPS. Définissez la propriété DesiredAccuracy sur Default (par défaut) afin d'acquérir la localisation avec une connexion Wi-Fi.</li>    <li><a href="http://fr.wikipedia.org/wiki/IP_address" target="_blank">IP</a> : une résolution de niveau IP peut fournir une précision allant jusqu'à environ 1 kilomètre. En cas de connexion réseau, le renvoi des données de localisation peut être plus rapide que l'acquisition d'une connexion satellite par un GPS. Vous pouvez définir la propriété DesiredAccuracy sur Default (par défaut) pour acquérir la localisation avec IP. Le service de localisation renvoie la précision la plus élevée possible et vous en fait connaître le niveau dans la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.devices.geolocation.geocoordinate.accuracy.aspx" target="_blank">Geocoordinate.Accuracy</a>.</li> </ul>  <p>Choisissez la précision voulue avec attention. Elle peut affecter les performances et la consommation énergétique de votre application. Par exemple, si votre application fournit des prévisions météorologique, vous avez rarement besoin de la précision élevée du GPS. Veillez par ailleurs à indiquer la précision de vos données en affichant un rayon d'erreur basé sur la précision des données renvoyées. Voici le code C# permettant de définir votre précision voulue :</p>  <p><strong>C#</strong></p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Geolocator geolocator = <span style="color: rgb(0, 0, 255);">new</span> Geolocator();<br />geolocator.DesiredAccuracy = Windows.Devices.Geolocation.PositionAccuracy.High;<br /></pre>
  </div>
</blockquote>

<br />Quelle que soit la précision souhaitée, l'appel permettant d'obtenir votre localisation est le suivant : 

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Geoposition pos = await geolocator.GetGeopositionAsync().AsTask(token);</pre>
  </div>
</blockquote>

<p>Ce code JavaScript permet de créer une instance de la classe Geolocator, de définir la précision voulue, puis d'obtenir la localisation actuelle. Notez que la variable « promise » ci-dessous est un objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211867.aspx" target="_blank">WinJS.Promise</a>. Vous devez utiliser la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh701079.aspx" target="_blank">done</a> pour accéder aux données depuis l'appel à <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br225537.aspx" target="_blank">getGeopositionAsync</a>.</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> geolocator = Windows.Devices.Geolocation.Geolocator();<br />geolocator.desiredAccuracy =<br />Windows.Devices.Geolocation.PositionAccuracy.high;<br /><br /><span style="color: rgb(0, 128, 0);">// Get the geoposition, capturing the request in a 'promise' object.</span><br /><span style="color: rgb(0, 0, 255);">var</span> promise = geolocator.getGeopositionAsync();<br /></pre>
  </div>
</blockquote>

<br />N'oubliez pas que si vous définissez votre précision voulue sur High (élevée), il n'est pas certain que le périphérique de l'utilisateur soit capable de renvoyer une précision élevée. Il est possible que son PC ne soit pas doté d'un GPS, que le GPS soit désactivé ou qu'aucune connexion Wi-Fi ne soit établie, etc. Soyez toujours prêt à bien gérer les cas de précision moindre des données. Pour cela, tout dépend des fonctionnalités de votre application. Pouvez-vous continuer avec une précision moindre ? Pouvez-vous demander un niveau de précision GPS ? Consultez les <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465148.aspx" target="_blank">Recommandations pour les applications prenant en charge la géolocalisation</a> pour en savoir plus. 

<h3>Cartes Bing</h3>

<p>L'<a href="http://apps.microsoft.com/webpdp/app/97a2179c-38be-45a3-933e-0d2dbf14a142" target="_blank">application Cartes Bing</a> est un bon exemple d'application qui s'adapte à la précision des données de localisation qui lui sont proposées. Sur un ordinateur de bureau, qui n'est généralement pas doté d'un GPS ou d'une connexion Wi-Fi, elle recherche la localisation en fonction de l'adresse IP et <a>zoome sur une région lorsqu'elle affiche </a>la position géographique actuelle sur la carte. Sur un ordinateur portable, qui comporte généralement une carte sans fil, elle utilise la connexion Wi-Fi pour obtenir une localisation plus précise et affiche la position géographique actuelle avec un zoom plus important. Si l'utilisateur zoome encore plus, l'icône de localisation actuelle présente un rayon d'erreur. Sur un périphérique avec GPS, Cartes Bing reçoit les données de localisation d'une précision élevée de la part du GPS et affiche une position géographique plus précise.</p>

<h3>Bing Météo</h3>

<p>Comme indiqué ci-dessus, une application telle que l'<a href="http://apps.microsoft.com/webpdp/app/421ba874-f903-4965-9b82-d60f3ba3cae0" target="_blank">application Bing Météo</a> n'a besoin que d'informations régionales. Elle peut ainsi indiquer qu'elle n'a besoin que d'une précision faible et renvoyer rapidement une valeur de localisation. Cela permet à l'application d'être plus réactive aux yeux des utilisateurs. Parmi les autres applications qui ne nécessitent que des informations au niveau régional se trouvent les guides des stations de radio, certaines offres commerciales ou les flux d'actualités locales.</p>

<h2>Affichage de données de localisation avec le SDK Cartes Bing</h2>

<p>Après avoir obtenu les informations de localisation suite à votre appel à <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.devices.geolocation.geolocator.getgeopositionasync.aspx" target="_blank">GetGeopositionAsync</a>, vous pouvez les afficher sur une carte.</p>

<ul>
  <li>Commencez par convertir la classe <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.devices.geolocation.geoposition.aspx" target="_blank">Geoposition</a> en classe <a href="http://msdn.microsoft.com/fr-fr/library/hh846500.aspx" target="_blank">Location</a> pouvant être utilisée avec Cartes Bing. Pour ce faire, utilisez le code suivant :</li>
</ul>

<p> </p>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Location location = <span style="color: rgb(0, 0, 255);">new</span> Location(pos.Coordinate.Latitude, pos.Coordinate.Longitude);</pre>
  </div>
</blockquote>

<p><strong>JavaScript :</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">promise.done(<br />  <span style="color: rgb(0, 0, 255);">function</span> (pos) {<br />    <span style="color: rgb(0, 128, 0);">// Get the coordinates of the current location.</span><br />    <span style="color: rgb(0, 0, 255);">var</span> coord = pos.coordinate,<br />    location = <span style="color: rgb(0, 0, 255);">new</span> Microsoft.Maps.Location(coord.latitude, coord.longitude);<br /> <br />  },<br />  <span style="color: rgb(0, 0, 255);">function</span> (err) {<br />    <span style="color: rgb(0, 128, 0);">// Handle the error.</span><br />  });<br /></pre>
  </div>
</blockquote>

<p> </p>

<ul>
  <li>Affichez ensuite votre localisation avec Cartes Bing. Vous pouvez obtenir le SDK Cartes Bing <a href="http://visualstudiogallery.msdn.microsoft.com/bb764f67-6b2c-4e14-b2d3-17477ae1eaca">ici</a>. Vous devez également obtenir une clé Cartes Bing en vous inscrivant sur le portail Cartes Bing et en suivant les instructions d'<a href="http://msdn.microsoft.com/fr-fr/library/ff428642.aspx">obtention d'une clé Cartes Bing</a>. Au moment de l'inscription, n'oubliez pas de regarder les restrictions d'utilisation de chaque type de clé et choisissez celle qui convient le mieux à votre application. 

    <br />Ajoutez un contrôle Cartes Bing à votre concepteur et insérez votre clé dans les informations d'identification.</li>
</ul>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Page</span><br />    <span style="color: rgb(255, 0, 0);">xmlns</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:x</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:local</span><span style="color: rgb(0, 0, 255);">=&quot;using:SimpleMapping&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:d</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:mc</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:Maps</span><span style="color: rgb(0, 0, 255);">=&quot;using:Bing.Maps&quot;</span><br />    <span style="color: rgb(255, 0, 0);">x:Class</span><span style="color: rgb(0, 0, 255);">=&quot;SimpleMapping.MainPage&quot;</span><br />    <span style="color: rgb(255, 0, 0);">mc:Ignorable</span><span style="color: rgb(0, 0, 255);">=&quot;d&quot;</span><span style="color: rgb(0, 0, 255);">&gt;</span><br /><br />    <span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Grid</span> <span style="color: rgb(255, 0, 0);">Background</span><span style="color: rgb(0, 0, 255);">=&quot;{StaticResource ApplicationPageBackgroundThemeBrush}&quot;</span><span style="color: rgb(0, 0, 255);">&gt;</span><br />        <span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Maps:Map</span> <span style="color: rgb(255, 0, 0);">x:Name</span><span style="color: rgb(0, 0, 255);">=&quot;Map&quot;</span> <span style="color: rgb(255, 0, 0);">Margin</span><span style="color: rgb(0, 0, 255);">=&quot;0,120,0,0&quot;</span> <span style="color: rgb(255, 0, 0);">Credentials</span><span style="color: rgb(0, 0, 255);">=&quot;Insert Your Bing Maps Key Here&quot;</span><span style="color: rgb(0, 0, 255);">/&gt;</span><br />    <span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">Grid</span><span style="color: rgb(0, 0, 255);">&gt;</span><br /><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">Page</span><span style="color: rgb(0, 0, 255);">&gt;</span></pre>
  </div>
</blockquote>

<ul>
  <li>Vous pouvez maintenant utiliser le code suivant sur la page de votre application où la carte apparaît. Cette opération définit le niveau de zoom de la carte et affiche la localisation. Pour en savoir plus sur le niveau de zoom, consultez <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/jj850315.aspx" target="_blank">Comment afficher votre localisation sur une carte Bing</a> :</li>
</ul>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">double</span> zoomLevel = 13.0f;<br /><br />Map.SetView(location, zoomLevel);<br /></pre>
  </div>
</blockquote>

<br />L'ajout d'un contrôle Cartes Bing à votre application dans JavaScript et HTML nécessite un peu plus de travail. Ajoutez la balise &lt;script&gt; suivante au code HTML de votre application : 

<div> </div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">script</span> <span style="color: rgb(255, 0, 0);">type</span><span style="color: rgb(0, 0, 255);">=&quot;text/javascript&quot;</span> <br />   <span style="color: rgb(255, 0, 0);">src</span><span style="color: rgb(0, 0, 255);">=&quot;ms-appx:///Bing.Maps.JavaScript//js/veapicore.js&quot;</span><span style="color: rgb(0, 0, 255);">&gt;</span><br />/script<span style="color: rgb(0, 0, 255);">&gt;</span><br /></pre>
  </div>
</blockquote>

<p>Vous devez ensuite créer une balise &lt;div&gt; qui contiendra la carte, en définissant l'attribut id de façon à pouvoir y accéder.</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">div</span> <span style="color: rgb(255, 0, 0);">id</span>=’<span style="color: rgb(255, 0, 0);">map-div</span>’<span style="color: rgb(0, 0, 255);">&gt;&lt;/</span><span style="color: rgb(128, 0, 0);">div</span><span style="color: rgb(0, 0, 255);">&gt;</span></pre>
  </div>
</blockquote>

<p>Dernière opération : vous devez initialiser le contrôle de carte dans la page HTML. Voici un code JavaScript correspondant :</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 128, 0);">// Load the Microsoft.Maps.Map module and then call getMap when the </span><br /><span style="color: rgb(0, 128, 0);">// module has loaded.</span><br /><span style="color: rgb(0, 0, 255);">function</span> initMap() {<br />  Microsoft.Maps.loadModule(<span style="color: rgb(0, 96, 128);">'Microsoft.Maps.Map'</span>, <br />    { <br />      callback: getMap, <br />      culture: <span style="color: rgb(0, 96, 128);">&quot;en&quot;</span>, <br />      homeRegion: <span style="color: rgb(0, 96, 128);">&quot;US&quot;</span> <br />  });<br />}<br /><br /><span style="color: rgb(0, 128, 0);">// Get the div to contain the map from the interface of the app.</span><br /><span style="color: rgb(0, 0, 255);">function</span> getMap() {<br /><br />  <span style="color: rgb(0, 128, 0);">// Create a new instance of the Map class, passing in the app ID.</span><br />  <span style="color: rgb(0, 0, 255);">var</span> map = <span style="color: rgb(0, 0, 255);">new</span> Microsoft.Maps.Map(<br />    document.getElementById(mapDivId), <br />    { credentials: “Insert your credentials here” });<br /><br />  <span style="color: rgb(0, 128, 0);">// Set the initial zoom level and type of map.</span><br />  map.setView({<br />    mapTypeId: Microsoft.Maps.MapTypeId.road,<br />    zoom: 3<br />  });<br />}<br /></pre>
  </div>
</blockquote>

<ul>
  <li>Enfin, toutes les applications qui utilisent la localisation doivent respecter les paramètres d'autorisation de l'utilisateur, susceptibles de changer à tout moment. L'application Météo utilise la localisation pour obtenir la météo de l'emplacement actuel. Mais l'utilisateur peut à tout moment accéder aux paramètres et désactiver les autorisations liées à la localisation. Votre application doit toujours faire face à la possibilité d'une désactivation des autorisations liées à la localisation. Dans ce cas, l'application Météo affiche un message du type « Votre localisation est introuvable. Modifiez vos autorisations pour autoriser l'application Météo à utiliser votre localisation. ». Consultez les <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/Hh465148(v=win.10).aspx" target="_blank">Recommandations pour les applications prenant en charge la géolocalisation</a> pour voir des exemples de gestion des autorisations de localisation. 

    <br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0882.bing-weather_2FEEBCEF.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0882.bing_2D00_weather_5F00_2FEEBCEF.jpg"><img title="Application Bing Météo" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Utilisation de la localisation par l'application Bing Météo pour connaître la météo de l'emplacement actuel" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7356.bing-weather_thumb_084840C5.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7356.bing_2D00_weather_5F00_thumb_5F00_084840C5.jpg" width="600" height="450" /></a></li>
</ul>

<p> </p>

<p>Pour en savoir plus sur la géolocalisation et le SDK Cartes Bing, <a></a><a>nous proposons une nouvelle </a><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/jj850315.aspx" target="_blank">rubrique détaillée avec vidéo</a>, ainsi qu'un <a href="http://code.msdn.microsoft.com/windowsapps/Simple-geolocation-with-7b385c3c" target="_blank">exemple de code</a> qui vous explique comment acquérir de manière asynchrone votre localisation, puis comment utiliser le SDK Cartes Bing pour visualiser votre position géographique. La vidéo, la rubrique détaillée et l'exemple vous indiquent comment activer la fonctionnalité de localisation, obtenir la localisation de manière asynchrone, définir la carte sur une localisation donnée et définir l'icône de localisation en fonction de la précision des données de localisation. Vous trouverez également plus d'informations dans <a href="http://msdn.microsoft.com/fr-fr/library/hh846481.aspx" target="_blank">Bing Maps for Windows Store Apps</a>.</p>

<h2>Pour résumer</h2>

<p>L'ajout de la localisation dans votre application peut vous faire gagner du temps. Cette fonctionnalité vous permet d'offrir à l'utilisateur des informations plus pertinentes en fonction de sa position géographique. Qu'il s'agisse d'une liste de stations de radio locales, d'offres commerciales, de conditions de circulation ou d'informations météorologiques, la capacité d'adapter ces données en fonction de la localisation peut accroître l'utilité de votre application. En outre, la possibilité de rendre tout le processus automatique, sans que l'utilisateur n'ait besoin d'intervenir, permet à ce dernier de gagner du temps et augmente les chances qu'il utilise votre application.</p>

<p>--Ross Heise, Développeur de contenu, Contenu de développement Windows</p>
<p>   Remerciements tout particuliers à Jon Kay et Eric Schmidt pour leur aide et leur participation à ce billet.</p>
<!-- Title: “Créer des applications prenant en charge la localisation avec la géolocalisation et l'application Cartes Bing” Tags: “Cartes Bing, géolocalisation, Windows. Devices. Geolocation, services de localisation” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Présentation d'une nouvelle expérience du Centre de développement Windows</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/prsentation-dune-nouvelle-exprience-du-centre-de-dveloppement-windows</link>
      <pubDate>Thu, 16 May 2013 09:50:39 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/05/16/prsentation-dune-nouvelle-exprience-du-centre-de-dveloppement-windows/</guid>
      <description><![CDATA[Depuis le lancement du Centre de développement Windows en octobre 2011, nous avons travaillé en...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Depuis le lancement du <a href="http://msdn.microsoft.com/fr-fr/windows/default.aspx" target="_blank">Centre de développement Windows</a> en octobre 2011, nous avons travaillé en étroite collaboration avec les développeurs et concepteurs du monde entier afin d'offrir les meilleurs conseils, avis et exemples aux concepteurs d'applications. Les millions de visiteurs et vos commentaires nous ont permis d'évaluer les points positifs et ce qui restait à améliorer.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0172.windows_dev_center_1EC86298.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0172.windows_5F00_dev_5F00_center_5F00_1EC86298.png"><img title="Centre de développement Windows" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Centre de développement Windows" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0184.windows_dev_center_thumb_1DEFFCAE.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0184.windows_5F00_dev_5F00_center_5F00_thumb_5F00_1DEFFCAE.png" width="600" height="338" /></a></p>  <h2>Nouveautés</h2>  <p>L'objectif de l'équipe Windows est de développer un écosystème d'applications dynamique et prospère. Cela s'exprime de trois manières : de formidables applications, de formidables débouchés commerciaux et de formidables opportunités de développement. Le nouveau Centre de développement permet aux concepteurs d'applications, développeurs et entreprises d'accéder aux ressources dont ils ont besoin pour réussir pleinement le développement de formidables applications et créer leur activité avec Windows.</p>  <p>Dans cette optique, le Centre de développement a évolué dans les domaines suivants :</p>  <ol>   <li>Le modèle de navigation a changé afin que vous puissiez trouver le contenu approprié au cycle de vie du développement d'application dans lequel vous vous trouvez.</li>    <li>La conception du site met en évidence les tâches principales, les scénarios clés et les nouveaux contenus. </li> </ol>  <p>Outre le contenu, les exemples et les téléchargements dont les développeurs ont besoin, nous avons également facilité l'accès aux ressources pour les concepteurs et les entreprises. </p>  <p>Selon ce que vous concevez, vous pouvez accéder à l'une de ces quatre rubriques : <a href="http://msdn.microsoft.com/fr-fr/windows/apps/br229512" target="_blank">Applications du Windows Store</a>, <a href="http://msdn.microsoft.com/fr-fr/ie/" target="_blank">Internet Explorer</a>, <a href="http://msdn.microsoft.com/fr-fr/windows/desktop" target="_blank">Bureau Windows</a> et <a href="http://msdn.microsoft.com/fr-fr/windows/hardware" target="_blank">Matériel</a>. Chaque rubrique présente une nouvelle expérience qui répond aux points soulevés ci-dessus. Dans ce billet, nous allons examiner de plus près les modifications spécifiques apportées à la rubrique Applications du Windows Store.</p>  <h2>Un contenu adapté à votre rôle</h2>  <p>Le site le mieux documenté ne vous sera pas utile si vous ne trouvez pas ce dont vous avez besoin. Avec les centaines de milliers de rubriques du Centre de développement, l'organisation et la recherche du contenu sont des critères essentiels. En ce qui concerne le développement d'applications du Windows Store, cela signifie un affinement des recherches en fonction du rôle et du scénario (en mettant à votre disposition dont ce dont vous avez besoin pour commencer au même endroit pour parvenir à une assistance plus appropriée pour les concepteurs et les entreprises). Voici quelques-unes des principales améliorations.</p>  <h3>Développeurs</h3>  <p>Nous avons rationalisé le contenu dont vous avez besoin pour créer de formidables applications du Windows Store. La <a href="http://msdn.microsoft.com/fr-fr/windows/apps/" target="_blank">page d'accueil Applications du Windows Store</a> présente les éléments suivants : </p>  <ul>   <li>La section « Principaux contenus et tâches » apparaît au premier plan pour vous aider à accéder au contenu qui vous intéresse. Les événements locaux dans votre région sont mis en évidence, ainsi que les nouvelles ressources récemment ajoutées au site. </li>    <li>Des téléchargements ont pour but de vous aider à programmer et vous trouverez toutes les ressources dont vous avez besoin pour démarrer, ainsi que nos conseils détaillés pour transférer votre application dans le Windows Store. </li>    <li>Des exemples de code importants sont mis en évidence, et la consultation des rubriques d'aide est simplifiée et plus centrée sur le cycle de vie de développement. </li>    <li>Des vidéos « <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211360.aspx" target="_blank">One Dev Minute</a> » présentes sur tout le site vous permettent de savoir rapidement comment ajouter des fonctionnalités à votre application. </li> </ul>  <h3>Concepteurs</h3>  <p>Nous avons remanié la <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh779072.aspx" target="_blank">section Concevoir</a> du site afin d'en faciliter l'utilisation et de la compléter. Vous y trouverez plus facilement des téléchargements utiles et des ressources de conception réutilisables, ainsi que des idées de conception et des études de cas qui vous donnent les clés dont vous avez besoin pour vivre une expérience unique sur Windows. Tout ce qui est nécessaire pour concevoir une application magnifique qui sorte du lot se trouve à portée de main, avec une mise en page conviviale et simple d'utilisation.</p>  <h3>Entreprises</h3>  <p>Les débouchés commerciaux que représente le Windows Store sont importants, avec un meilleur modèle économique que les plateformes concurrentes et une flexibilité supérieure qui vous permet de créer l'activité que vous voulez. La nouvelle <a href="http://go.microsoft.com/fwlink/?LinkID=285998" target="_blank">section Commercialiser</a> du site fournit de précieux conseils sur la commercialisation de vos applications, sur l'évaluation des données télémétriques et sur la réussite de la certification de vos applications. Nous avons beaucoup appris sur la façon dont nous pouvions simplifier la certification et avons amélioré le contenu pour vous aider à suivre plus rapidement le processus.</p>  <p>Évidemment, vous êtes nombreux à remplir plusieurs rôles et nous pensons que la nouvelle organisation du site vous aidera également dans ce cas. La nouvelle organisation du site permettra à tous les acteurs d'atteindre leurs objectifs avec Windows, qu'il s'agisse d'amateurs ou d'agences de création en passant par les éditeurs de logiciels les plus importants.</p>  <h2>Ce n'est qu'un début et nous voudrions entendre votre avis</h2>  <p>Avec la conférence <a href="http://www.buildwindows.com">BUILD 2013</a> qui se tient dans un peu plus d'un mois, beaucoup de sujets restent à aborder. Nous travaillons d'arrache-pied pour produire de nouveaux contenus à partager lors de la conférence. Outre ce blog, vous pouvez également vous tenir au courant des derniers événements en suivant <a href="https://twitter.com/#!/windevs" target="_blank">@windevs</a> sur Twitter et en vous abonnant au <a href="http://www.windowsstore.com/newsletter-signup" target="_blank">bulletin d'informations du Windows Store</a>.</p>  <p>Parallèlement au lancement de contenus supplémentaires pour vous aider à concevoir, développer et commercialiser vos applications du Windows Store, nous voulons continuer à améliorer l'utilisation du Centre de développement. Afin que vous puissiez nous dire plus facilement ce que vous pensez, nous avons proposé deux nouvelles options d'envoi des commentaires au bas de chaque page. N'hésitez pas à nous donner votre avis. Nous en prenons connaissance et faisons toujours tout notre possible pour répondre à vos attentes.</p>  <p> </p>  <p>Keith Boyd, Responsable de la publication de contenu, Contenu de développement Windows</p> <!-- Title: “Présentation d'une nouvelle expérience du Centre de développement Windows” Tags: “Centre de développement, informations de développement, conception d'applications, applications du Windows, créer, Centre de développement Windows” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Partage vers votre application cible</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/partage-vers-votre-application-cible</link>
      <pubDate>Wed, 15 May 2013 09:10:42 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/05/15/partage-vers-votre-application-cible/</guid>
      <description><![CDATA[Dans le billet Partage à partir de votre application, nous avons présenté le concept de partage de...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Dans le billet <a href="http://blogs.msdn.com/b/windowsappdev_fr/archive/2012/12/21/partage-224-partir-de-votre-application.aspx" target="_blank">Partage à partir de votre application</a>, nous avons présenté le concept de partage de contenu à partir de l'exemple d'application <a href="http://blogs.msdn.com/b/windowsappdev_fr/archive/2012/07/18/cr-233-ation-d-applications-de-style-metro-qui-sortent-du-lot.aspx" target="_blank">Food with Friends</a>. Dans ce billet, les contenus sont partagés avec plusieurs applications cibles qui permettent à l'utilisateur de mener à bien l'intégralité de différents scénarios complexes. Les applications de Windows 8 offrent des contenus intéressants que vos clients souhaiteront certainement <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465251.aspx" target="_blank">partager</a> avec leurs amis ou avec d'autres applications. Si vous réussissez à faire de votre application une cible de partage convaincante et bien conçue, elle peut devenir pour vos clients le véritable cœur d'une expérience sociale et connectée.</p>  <p>Dans ce billet, nous examinons comment vous pouvez utiliser le contrat de partage cible avec vos applications, en particulier avec les applications de type « Food with Friends ». Grâce à ce contrat, votre application peut <i>recevoir des contenus</i> issus d'autres applications et utiliser ces contenus pour les enrichir. Notre objectif : vous aider à faire de votre application la meilleure de sa catégorie !</p>  <p>Pour créer une application cible, vous devez utiliser le <a href="http://blogs.msdn.com/b/b8_fr/archive/2012/06/14/activation-des-contrats-windows-160-8-dans-votre-application.aspx" target="_blank">contrat</a><u></u> de partage cible. Les applications cibles permettent de partager facilement et rapidement des contenus. Toutes les applications Windows ne peuvent pas être utilisées comme cibles de partage. Cependant, si votre application peut publier les contenus issus d'autres applications, les transformer, les stocker ou y ajouter une quelconque valeur, la création d'une cible de partage offre de nombreux avantages. </p>  <ul>   <li>Votre application apparaîtra toujours dans la liste des applications cibles. Elle offre instantanément des informations pertinentes et elle est connectée à d'autres applications qui peuvent partager les données que vous souhaitez. </li>    <li>Le contrat de partage crée un pont entre votre application et n'importe quelle application source, sans que l'une ou l'autre des applications ait besoin de prévoir une intégration spécifique avec l'autre application. </li>    <li>Comme l'icône Partager est toujours présente et disponible dans le système d'exploitation, elle permet à votre application cible d'être présente dans le système d'exploitation, bien au-delà des limites de votre application. Ainsi, plus de clients peuvent potentiellement être dirigés vers votre application !</li> </ul>  <h2>Réception des contenus partagés</h2>  <p>Examinons quelques exemples qui vous montrent comment proposer des expériences utilisateur convaincantes par le biais d'une application cible de partage.</p>  <p>Vous connaissez peut-être déjà les applications Courrier et Contacts de Windows 8. Courrier crée une expérience de cible de partage extrêmement simple et personnalisée, permettant de recevoir et de partager des contenus avec un ou plusieurs amis. L'application Contacts vous permet de partager des contenus avec des publics plus larges sur vos réseaux sociaux. En plus du partage social, vous pouvez aller encore plus loin avec le partage d'application dans l'application. Les applications de productivité telles que SkyDrive peuvent recevoir des fichiers de tous les emplacements de Windows et les stocker sur le cloud. Les applications de prise de notes peuvent recevoir du texte, des liens et éventuellement des données dans de nombreux autres formats et les archiver, en vue d'une consultation ultérieure. Vous profitez également d'une grande marge de créativité. </p>  <p>Observez comment, sur les deux images ci-dessous, le processus de partage apparaît lors du partage d'une photo à partir de l'application Photos avec PuzzleTouch, une application de jeu qui transforme l'image en puzzle visuel. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8637.puzzletouch1_6E4332DA.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8637.puzzletouch1_5F00_6E4332DA.png"><img title="L'application source apparaît à gauche, tandis que la liste filtrée des applications cibles pouvant recevoir des photos apparaît à droite dans le volet Partager. " style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="L'application source apparaît à gauche, tandis que la liste filtrée des applications cibles pouvant recevoir des photos apparaît à droite dans le volet Partager. " src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1307.puzzletouch1_thumb_2681A9F3.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1307.puzzletouch1_5F00_thumb_5F00_2681A9F3.png" width="700" height="394" /></a></p>  <p align="center"><i>Figure 1 : l'application source apparaît à gauche, tandis que la liste filtrée des applications cibles pouvant recevoir des photos apparaît à droite dans le volet Partager.      <br />PuzzleTouch fait partie des cibles de partage pouvant recevoir une image issue de l'application Photos. </i></p>  <p align="left"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/6661.puzzletouch2_463083BB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/6661.puzzletouch2_5F00_463083BB.png"><img title="Dans la partie droite, l'aperçu de l'application cible permet à l'utilisateur de sélectionner le type de puzzle à créer" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Dans la partie droite, l'aperçu de l'application cible permet à l'utilisateur de sélectionner le type de puzzle à créer" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/2474.puzzletouch2_thumb_65DF5D83.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/2474.puzzletouch2_5F00_thumb_5F00_65DF5D83.png" width="700" height="394" /></a></p>  <p align="center"><i>Figure 2 : dans la partie droite, l'aperçu de l'application cible permet à l'utilisateur de sélectionner le type de puzzle      <br />à créer. Le puzzle est prêt dès que l'utilisateur accède de nouveau à l'application. </i></p>  <h2>Qu'est-ce qu'une application cible de partage ?</h2>  <p>Dans Windows , l'expérience de partage se compose de deux éléments. Elle comprend tout d'abord d'une application source qui met son contenu à la disposition de Windows, dans différents formats. Vient ensuite une application cible de partage, qui indique à Windows qu'elle reconnaît certains formats et qui sert de destination pour le contenu partagé. Grâce au contrat de partage, l'application source et l'application cible de partage peuvent communiquer.</p>  <p>Lorsque vous réfléchissez à l'expérience de partage de votre application, prenez en compte le fait que l'application cible de partage est affichée dans la fenêtre de partage hébergée. Concevez l'expérience de telle sorte que l'utilisateur puisse afficher rapidement un aperçu de son contenu et confirmer le partage dans cette vue. Cet exemple représente la vue d'application cible de partage de l'application Courrier, qui permet à l'utilisateur de partager rapidement un lien à partir du navigateur avec un ou plusieurs contacts de messagerie. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8561.Share-Target-Image_3ED44139.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8561.Share_2D00_Target_2D00_Image_5F00_3ED44139.png"><img title="Image de cible de partage" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Image de cible de partage" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/6011.Share-Target-Image_thumb_4FD86F1C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/6011.Share_2D00_Target_2D00_Image_5F00_thumb_5F00_4FD86F1C.png" width="700" height="435" /></a></p>  <p align="center"><i>Figure 3 : partage d'un lien à partir de l'application Photos avec l'application cible Courrier</i></p>  <h2>Scénarios pour Food with Friends</h2>  <p>Voyons maintenant comment <a href="http://blogs.msdn.com/b/windowsappdev_fr/archive/2012/07/18/cr-233-ation-d-applications-de-style-metro-qui-sortent-du-lot.aspx" target="_blank">Food with Friends</a> crée une expérience convaincante d'application cible de partage. Si vous connaissez déjà l'application, vous savez que dans Food with Friends, l'utilisateur peut entreprendre deux actions principales : <i>créer un programme</i> et <i>ajouter un restaurant à sa liste d'envies</i>. Bien évidemment, d'autres opérations sont réalisables : rédaction d'un avis, publication d'un commentaire, affichage des listes d'envies des amis, etc. Toutefois, ces expériences sont uniquement mises en œuvre dans le contexte de l'application principale. Pour les deux scénarios principaux, faisons un petit test pour vérifier s'ils peuvent être menés à bien de façon efficace via l'application cible Food with Friends.</p>  <h3>Créer le programme de la soirée</h3>  <p>S'il fait partie des scénarios essentiels de l'application principale, il ne s'agit pas du scénario idéal dans le cadre d'une expérience de cible de partage. Voici pourquoi : l'expérience de cible de partage est censée être rapide et simple. Or la création d'un programme est une tâche bien plus complexe : dans ce cas, l'utilisateur souhaite savoir quels restaurants ses amis veulent essayer, comparer quelques restaurants figurant dans la liste d'envies, passer les notes en revue, etc. Comme la planification implique d'exploiter des détails qui sont mieux présentés dans la vue de l'application principale, il n'est pas très judicieux de condenser cette fonctionnalité dans l'application cible du partage. </p>  <p><b></b></p>  <h3>Ajouter à la liste d'envies</h3>  <p>Ce scénario fonctionne parfaitement bien en tant que tâche courte et guidée dans la cible de partage. Voici quelques-uns des principaux aspects de cette expérience dans l'application :<b></b></p>  <ul>   <li>Les utilisateurs trouvent des restaurants dans d'autres applications (applications d'organisation de voyages, applications consacrées à une ville précise et comportant des recommandations, blogs consacrés à la gastronomie, etc.). Food with Friends est une destination idéale pour regrouper des restaurants dans la section « Ma liste d'envies ». </li>    <li>La vue d'application cible d'une application est conçue pour permettre à l'utilisateur d'entreprendre rapidement une action dans le contexte d'une autre application. Ainsi, l'ajout d'un restaurant à une liste d'envies est une option idéale à faire apparaître dans la cible de partage. </li>    <li>S'il est certainement possible pour l'utilisateur de changer d'application, de relancer la recherche afin de trouver le restaurant, puis d'ajouter le restaurant à sa liste d'envies, il est bien plus rapide d'appuyer sur Partager.</li> </ul>  <p>La liste d'envies de Food with Friends offre donc a priori une formidable expérience d'application cible de partage, que nous souhaitons donc concevoir et créer. Voici le scénario complet auquel nous avons pensé :</p>  <p>En parcourant une application qui recense les restaurants ambulants à proximité, je découvre une recommandation qui m'a l'air intéressante. Je souhaite ajouter le restaurant ambulant indiqué dans cette application à ma liste d'envies Food with Friends, pour faciliter la planification ultérieure.</p>  <p align="center"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7658.contoso_truck_6C263411.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7658.contoso_5F00_truck_5F00_6C263411.png"><img title="Navigation dans une application qui affiche les restaurants ambulants à proximité et recommande les lieux intéressants" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Navigation dans une application qui affiche les restaurants ambulants à proximité et recommande les lieux intéressants" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3022.contoso_truck_thumb_4B9EF45F.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3022.contoso_5F00_truck_5F00_thumb_5F00_4B9EF45F.png" width="700" height="394" /></a><em>Figure 4 : navigation dans une application qui affiche les restaurants ambulants à proximité et recommande les lieux intéressants</em></p>  <p>Cette image représente la vue d'application cible de partage que nous souhaitons utiliser :</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3835.contoso_truck2_565C4BB4.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3835.contoso_5F00_truck2_5F00_565C4BB4.png"><img title="Vue d'application cible de partage" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Vue d'application cible de partage" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8637.contoso_truck2_thumb_760B257C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8637.contoso_5F00_truck2_5F00_thumb_5F00_760B257C.png" width="700" height="394" /></a></p>  <p align="center"><em>Figure 5 : vue d'application cible de partage</em></p>  <p>En réalisant l'action de partage dans la vue d'application cible, les utilisateurs peuvent choisir des restaurants dans Food with Friends sans sortir du contexte de leur expérience actuelle d'application immersive. </p>  <h2>Implémentation d'une cible de partage</h2>  <p>Maintenant que vous avez découvert quelques exemples montrant quand implémenter une cible de partage, examinons comment implémenter notre cible de partage. Nous devons tout d'abord définir les formats de données que votre application devra accepter. </p>  <h3>Quels formats de données devez-vous prendre en charge ?</h3>  <p>Avec le partage, vous pouvez prendre en charge des formats de données standard (texte, URI, HTML, images bitmap, fichiers, etc.) ou des formats de données personnalisés, tels que ceux qui figurent sur <a href="http://schema.org" target="_blank">http://schema.org</a>. Windows filtre les applications cibles en fonction des formats de données qu'elles acceptent, afin d'afficher la liste filtrée des applications cibles dans le volet Partager. Votre application doit prendre en charge les formats de données les plus importants dans le cadre de l'expérience utilisateur de l'application. Par exemple, si votre application permet d'afficher des photos, il n'est sans doute pas nécessaire de prendre en charge les formats texte. Si vous déclarez la prise en charge de plusieurs formats de données, identifiez celui qui vous aide à représenter le mieux les données partagées, pour sélectionner ce format en premier dans le package de données. </p>  <p>Comme Food with Friends implémente une expérience de cible de partage qui permet aux utilisateurs de partager des restaurants vers l'application, nous utiliserons le format de données <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a><u></u> disponible sur <a href="http://schema.org" target="_blank">http://schema.org</a>. Food with Friends peut s'inscrire auprès du contrat de partage cible afin de recevoir ce format de données. À partir des données disponibles dans le package reçu, l'application peut ensuite créer une expérience convaincante dans sa vue d'application cible, qui permet à l'utilisateur d'ajouter ce restaurant à sa liste d'envies. </p>  <p>Si certaines applications sources peuvent partager des données en utilisant spécifiquement le format de données <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a><u></u>, d'autres applications sources peuvent représenter des informations similaires en utilisant d'autres formats, par exemple <a href="http://schema.org/Place" target="_blank">Place</a><u></u>, <a href="http://schema.org/LocalBusiness" target="_blank">LocalBusiness</a><u></u> ou <a href="http://schema.org/FoodEstablishment" target="_blank">FoodEstablishment</a>, qui figurent sur <a href="http://schema.org/" target="_blank">schema.org</a><u></u>. Ainsi, Food with Friends peut prendre en charge la réception de plusieurs formats de données dans le contrat de partage, pour s'adapter à une grande variété d'applications sources.</p>  <p>Food with Friends prend en charge les formats suivants dans les déclarations de cible de partage du manifeste de l'application :</p>  <ul>   <li><u><a href="http://schema.org/Restaurant" target="_blank">Restaurant</a></u></li>    <li><u><a href="http://schema.org/Place" target="_blank">Place</a></u></li>    <li><u><a href="http://schema.org/LocalBusiness" target="_blank">LocalBusiness</a></u></li>    <li><u><a href="http://schema.org/FoodEstablishment" target="_blank">FoodEstablishment</a></u><u></u></li> </ul>  <p><u></u></p>  <p>Pour plus de concision, nous nous concentrons ici sur le type de données <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a><u></u>, mais les concepts s'appliquent également à d'autres types de données.</p>  <h3>Quels formats de données et scénarios devez-vous prévoir ? </h3>  <p>Food with Friends ne permettra d'ajouter un restaurant à la liste d'envies de l'utilisateur que si les informations reçues concernant le restaurant correspondent à celles d'un restaurant que l'application connaît déjà. Ce comportement est voulu : il évite de créer plusieurs copies d'un même restaurant dans l'application. </p>  <p>Nous ne prenons pas en charge les types de données standards, car la plupart des contenus de type texte, fichiers, photos URI ou HTML partagés à partir d'applications sources ne sont pas associées à un restaurant ou à une entreprise locale. Par exemple, si Food with Friends prenait en charge la réception de texte, il apparaîtrait dans la liste des applications cibles d'une application source de prise de notes. Dans ce cas, Food With Friends devrait afficher un message d'erreur pour indiquer pourquoi cette application ne fonctionne pas avec telle ou telle application source. Au final, les formats de données jouent le rôle de lien entre l'application source, qui possède un contenu à proposer à une application cible, et l'application cible elle-même. Si les formats de données sont différents, il n'y a pas lieu de partager quoi que ce soit.</p>  <p>Pensez à prendre en compte tous les formats de données qui vous aident à identifier les informations importantes et à identifier les formats de données qui risqueraient de rendre l'expérience de partage trop généraliste.</p>  <h3>Prise en charge du contrat de partage cible</h3>  <p>Pour prendre en charge les formats de données, déclarez-les dans le concepteur de manifeste de votre application, dans Visual Studio. Voici ce qui se produit lorsqu'un utilisateur sélectionne votre application en tant que cible d'une action de partage :</p>  <ol>   <li>Une nouvelle instance de l'application est ouverte dans la fenêtre de la cible de partage, par-dessus l'application source. </li>    <li>Un événement d'<a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.activation.sharetargetactivatedeventargs.aspx" target="_blank">activation de cible de partage</a> est déclenché et votre application reçoit un objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br205977.aspx" target="_blank">ShareOperation</a><b></b> en tant que résultat.</li>    <li>Votre application peut récupérer les données que l'utilisateur a partagées à partir de cet objet. </li>    <li>Vous pouvez utiliser ces données pour générer la vue de l'application cible et terminer la procédure de partage initiée par l'utilisateur. </li> </ol>  <p>Pour plus d'informations sur la création de cette expérience, consultez le guide <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465255.aspx" target="_blank">Démarrage rapide :</a> <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465255.aspx"><u>réception d’un contenu partagé</u></a>. </p>  <p>Par ailleurs, Visual Studio prend en charge un modèle pour les cibles de partage. Cliquez avec le bouton droit de la souris sur votre projet, sélectionnez <b>Ajouter un élément</b>, <b>Ajouter un nouvel élément</b>, puis cliquez dans la liste sur <b>Contrat de partage cible</b> afin d'ajouter le code de prise en charge du contrat. L'<a href="http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782" target="_blank">exemple de code de cible de partage</a><u></u> montre comment recevoir du contenu partagé.</p>  <h2>Conception d'une vue d'application cible personnalisée</h2>  <p>Lorsque l'utilisateur sélectionne une application cible dans la liste des applications du volet Partager, Windows ouvre l'application dans la vue de cible de partage de l'application. La vue d'application cible est une vue spécifique hébergée dans le volet Partager. Elle diffère de la vue principale de l'application. Le billet <a href="http://blogs.msdn.com/b/b8_fr/archive/2012/06/14/activation-des-contrats-windows-160-8-dans-votre-application.aspx" target="_blank">Activation des contrats Windows 8 dans votre application</a><u></u> offre des informations complémentaires sur les vues hébergées et sur la gestion de l'activation de ces vues. La vue d'application cible est conçue pour vous aider à terminer l'action de partage initiée par l'utilisateur. Dans cette vue, les utilisateurs doivent être en mesure d'afficher un aperçu du contenu, d'entreprendre des actions simples et de confirmer leur souhait de partager le contenu. </p>  <p>Avant d'étudier la conception d'application cible de Food with Friends, examinons une application cible que vous connaissez peut-être déjà. Les images ci-dessous illustrent la vue d'application cible de l'application Courrier, ainsi que la vue complète de l'application dans <a></a>Windows 8.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1307.target-app_4AC68E75.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1307.target_2D00_app_5F00_4AC68E75.png"><img title="Partage à partir de l'application Photos vers l'application cible Courrier, située à droite" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Partage à partir de l'application Photos vers l'application cible Courrier, située à droite" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0724.target-app_thumb_5583E5CA.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0724.target_2D00_app_5F00_thumb_5F00_5583E5CA.png" width="700" height="438" /></a></p>  <p align="center"><i>Figure 6 : partage à partir de l'application Photos vers l'application cible Courrier, située à droite</i></p>  <p align="left"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1385.mail_154DCC50.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1385.mail_5F00_154DCC50.png"><img title="Rédaction d'un nouveau message dans la vue d'application principale de Courrier" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Rédaction d'un nouveau message dans la vue d'application principale de Courrier" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/2055.mail_thumb_510D6503.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/2055.mail_5F00_thumb_5F00_510D6503.png" width="700" height="438" /></a></p>  <p align="center"><em>Figure 7 : rédaction d'un nouveau message dans la vue d'application principale de Courrier</em></p>  <p>Vous remarquerez que la vue d'application cible de partage de Courrier est plus simple que la vue d'application complète. Elle offre un aperçu clair et minimaliste du contenu que l'utilisateur s'apprête à partager, présenté sous la forme d'une miniature agrémentée de texte et de contenus HTML. Elle offre une ligne <b>À</b> permettant d'ajouter des destinataires, une zone de saisie permettant de rédiger un court message, ainsi qu'un bouton <b>Envoyer</b>, qui permet de confirmer très simplement l'envoi du message.</p>  <p>Aussi simpliste soit-elle, la vue d'application cible de cette application est facilement identifiable en tant qu'avatar de l'application Courrier, ce qui renforce la confiance de l'utilisateur vis-à-vis de la destination du contenu partagé.</p>  <h2>Food with Friends en tant qu'application cible de partage</h2>  <p>Maintenant que vous comprenez mieux comment est conçue la vue d'application cible, examinons comment Food with Friends crée une application cible qui aide les utilisateurs à ajouter des restaurants à leur liste d'envies. </p>  <p>Lorsque Food with Friends reçoit le package de données contenant un <a href="http://schema.org/Restaurant">restaurant</a> en provenance de l'application source, il peut utiliser les détails figurant dans le format de données <a href="http://schema.org/Restaurant">Restaurant</a> pour identifier quel restaurant correspond au package de données reçu dans sa base de données existante. L'application peut ensuite afficher un aperçu de ce restaurant dans la vue d'application cible. La confiance de l'utilisateur vis-à-vis de l'intégrité du contenu partagé est ainsi renforcée. </p>  <p>Cette image représente la vue d'application cible de Food with Friends :</p>  <p align="center"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3857.contoso_truck3_0305058E.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3857.contoso_5F00_truck3_5F00_0305058E.png"><img title="Vue d'application cible de Food with Friends" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Vue d'application cible de Food with Friends" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5584.contoso_truck3_thumb_1B94A2DE.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5584.contoso_5F00_truck3_5F00_thumb_5F00_1B94A2DE.png" width="700" height="394" /></a><em>Figure 8 : vue d'application cible de Food with Friends</em></p>  <p>Comme vous pouvez le constater, cette vue de Food with Friends est simple et adaptée à une application cible de partage. Elle affiche un aperçu du restaurant que l'utilisateur s'apprête à partager, ainsi qu'un bouton simple, <b>Ajouter à la liste d'envies</b>, qui indique clairement la destination du contenu partagé dans l'application principale. Lorsque l'utilisateur appuie ou clique sur ce bouton, il confirme l'opération de partage. En obligeant l'utilisateur à appuyer ou à cliquer sur ce bouton, nous empêchons tout partage accidentel et nous améliorons la confiance de l'utilisateur vis-à-vis de l'expérience de partage globale. </p>  <p>Si l'application trouve plusieurs restaurants correspondant aux informations figurant dans le contenu du package de données, Food with Friends utilise la vue d'application cible de partage pour afficher des options et permettre à l'utilisateur de choisir celui qu'il souhaite partager. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5582.contoso_truck4_70500BD6.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5582.contoso_5F00_truck4_5F00_70500BD6.png"><img title="La vue d'application cible affiche des options permettant à l'utilisateur de choisir les éléments à partager" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="La vue d'application cible affiche des options permettant à l'utilisateur de choisir les éléments à partager" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/6175.contoso_truck4_thumb_6FE3D8E1.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/6175.contoso_5F00_truck4_5F00_thumb_5F00_6FE3D8E1.png" width="700" height="394" /></a></p>  <p align="center"><em>Figure 9 : la vue d'application cible affiche des options permettant à l'utilisateur de choisir les éléments à partager</em></p>  <p> </p>  <p>Si jamais l'application ne parvient pas à identifier précisément un restaurant ou un ensemble d'options valides à partir du package de données reçu, utilisez la vue d'application cible pour communiquer ce message. </p>  <h2>Création d'un QuickLink</h2>  <p>Un <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.quicklink.aspx" target="_blank">QuickLink</a> est une disposition de l'API de partage qui permet aux utilisateurs de partager des contenus vers des destinations courantes très rapidement, au sein de votre application cible. Un QuickLink joue le rôle de lien personnalisé vers votre vue cible, en fournissant des actions spécifiques. Lorsque Windows filtre la liste des applications cibles proposées à l'utilisateur, la liste des QuickLinks apparaît en haut du volet Partager, sous forme de liste des cibles disponibles. Ces destinations courantes ou ces actions utilisateurs peuvent inclure des emplacements ou des contacts qui sont souvent utilisés comme destination du partage dans l'application cible. Par exemple, l'application Courrier renvoie des QuickLinks pour les contacts précédemment utilisés comme destinataires. De même, vous pouvez ajouter des QuickLinks aux dossiers, groupes, blocs-notes et listes de lecture que vous partagez souvent vers votre application cible. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5001.quicklink_2FADBF67.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5001.quicklink_5F00_2FADBF67.png"><img title="Le volet Partager montre un QuickLink fourni par l'application cible Courrier pour les contacts qui ont été précédemment utilisés comme destinataires dans l'application cible" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Le volet Partager montre un QuickLink fourni par l'application cible Courrier pour les contacts qui ont été précédemment utilisés comme destinataires dans l'application cible" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1374.quicklink_thumb_334BDA44.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1374.quicklink_5F00_thumb_5F00_334BDA44.png" width="700" height="438" /></a></p>  <p align="center"><i>Figure 10 : le volet Partager montre un QuickLink fourni par l'application cible Courrier pour les contacts      <br />qui ont été précédemment utilisés comme destinataires dans l'application cible</i></p>  <p>L'application cible peut fournir un <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.quicklink.aspx" target="_blank">QuickLink</a><u></u> en appelant la méthode <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportcompleted.aspx" target="_blank">reportCompleted</a><u></u><b><u> </u></b>des objets<b><u> </u></b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br205977.aspx" target="_blank">ShareOperation</a><b></b><b><u> </u></b>. Un QuickLink doit posséder un titre, une icône et un ID. Le titre ("Envoyer un e-mail à maman", par exemple) et l'icône apparaissent lorsque l'utilisateur appuie sur l'icône Partager. L'ID est utilisé par votre application pour accéder à des informations personnalisées (adresse e-mail, emplacement de dossier, etc.). Pour en savoir plus sur cet outil, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh758299.aspx" target="_blank">Comment créer un objet QuickLink</a><u></u>.  </p>  <p>Remarque : les QuickLinks sont utiles lorsque l'application prend en charge plusieurs actions de l'application cible. Comme Food with Friends ne prend en charge qu'une seule action dans la cible de partage (<b>Ajouter à la liste d'envies</b>), l'application n'implémente pas de QuickLinks. </p>  <h2>Partage étendu et signalement des erreurs</h2>  <p>Dans certains cas, les applications sources partagent de gros volumes de données, par exemple des photos, des vidéos ou encore de gros fichiers, ce qui rallonge les temps de transfert. Ces types d'opérations de partage appelés <i>partages étendus</i> sont utilisés lorsque votre application cible peut avoir besoin de plus de temps pour recevoir et traiter les données. </p>  <p>Comme le partage doit être rapide et fluide, et que la vue d'application cible est une vue légère et hébergée, affichée par-dessus l'application principale, les utilisateurs sont susceptibles de sortir de la vue d'application cible pour revenir à l'application principale. Par conséquent, les applications cibles ne doivent pas exiger ni attendre une interaction de l'utilisateur avec la vue d'application cible après le démarrage du partage. Les applications cibles peuvent s'appuyer sur l'objet <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br205977.aspx" target="_blank">ShareOperation</a><b></b> et ses méthodes pour indiquer à Windows que l'application est en train de traiter des données. </p>  <ul>   <li><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportstarted.aspx" target="_blank">reportStarted</a></b> : appelez cette méthode pour indiquer à Windows que votre application a commencé à récupérer les données de l'objet DataPackage issu de l'application source. </li>    <li><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportdataretrieved.aspx" target="_blank">reportDataRetrieved</a></b><b><u> </u></b>: appelez cette méthode pour indiquer à Windows que votre application a terminé de récupérer les données du package.</li>    <li><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportcompleted.aspx" target="_blank">reportCompleted</a></b><b><u> : </u></b>appelez cette méthode pour indiquer à Windows que votre application a terminé l'opération de partage.<b><u> </u></b><b><u></u></b></li> </ul>  <p>Lorsque votre application traite les données d'un partage étendu, fournissez à l'utilisateur un indicateur de progression dans la vue d'application cible. L'utilisateur saura ainsi que sa demande est en cours de traitement, ce qui améliorera sa confiance vis-à-vis de l'application lorsqu'il accédera de nouveau à l'application pour consulter la progression de l'opération de partage. Pour en savoir plus sur les contrôles de progression dans Windows 8, consultez le guide <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465487.aspx" target="_blank">Démarrage rapide : ajout de contrôles de progression</a><u></u>. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0702.progress-bar_52FAB40C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0702.progress_2D00_bar_5F00_52FAB40C.png"><img title="Barre de progression" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Barre de progression" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3438.progress-bar_thumb_40B1ED4A.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3438.progress_2D00_bar_5F00_thumb_5F00_40B1ED4A.png" width="700" height="438" /></a></p>  <p align="center"><i>Figure 11 : l'application cible Courrier affiche une roue de progression pendant un partage étendu (envoi de pièces jointes volumineuses, par exemple)</i></p>  <p>Si quelque chose se passe mal au cours du transfert de données et que votre application cible doit arrêter l'opération de partage, vous pouvez appeler la méthode <b><u>reportError</u></b> pour envoyer un message d'erreur à Windows. L'utilisateur verra le message lorsqu'il consultera l'état du partage dans le volet Partager. Une fois l'erreur signalée, votre application est fermée et le partage est arrêté. L'utilisateur doit alors recommencer la procédure pour partage du contenu vers votre application.</p>  <p>Dans l'exemple de cible de partage Food with Friends, si l'application ne peut pas identifier dans sa base de données un restaurant correspondant à celui partagé à partir de l'application source via le format de données <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a><u></u>, l'application doit signaler une erreur. </p>  <h2>Révisons un peu !</h2>  <p>Le partage d'une application à une autre est une formidable opportunité pour les applications cibles de partage. En offrant à votre application la possibilité de recevoir des contenus partagés, vos utilisateurs profitent de votre application même lorsqu'ils réalisent une autre activité. Nous espérons que vous comprenez maintenant mieux les principes de conception, ainsi que les types de données, les classes et les propriétés que vous pouvez utiliser pour créer une formidable destination cible de partage. Nous sommes impatients de découvrir comment vos applications transformeront le contenu partagé et créeront des expériences toujours plus riches et plus complètes pour l'utilisateur final.</p>  <p>Pour en savoir plus sur le partage, commencez par consulter l'article <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh464923.aspx" target="_blank">Partage et échange de données</a><u></u> et l'<a href="http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782" target="_blank">exemple d'application cible de partage de contenu</a><u></u>.</p>  <p>Ishita Kapur</p>  <p>Chef de projet</p>  <p>Expérience utilisateur Windows</p> <!-- Title: “Partage vers votre application cible” Tags: “applications de partage, applications cibles, contenu partagé, cible de partage, applications cibles de partage” --> </div>]]></content:encoded>
    </item>
    <item>
      <title>Développer une application innovante grâce au NFC</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/dvelopper-une-application-innovante-grce-au-nfc</link>
      <pubDate>Wed, 24 Apr 2013 15:39:26 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/04/24/dvelopper-une-application-innovante-grce-au-nfc/</guid>
      <description><![CDATA[Le NFC (Near Field Communication) est une technologie émergente de communication sans fil en champ...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Le NFC (Near Field Communication) est une technologie émergente de communication sans fil en champ proche. Grâce à sa portée très précise de l'ordre de 2 cm, les utilisateurs peuvent mettre physiquement en contact deux appareils pour envoyer et recevoir des contenus. Cette opération vous permet de sélectionner quelque chose (ou quelqu'un) très rapidement. Le principe est non seulement rapide, mais aussi très facile à comprendre. Dès lorsque vous avez vu comment fonctionne cette technologie, vous avez tout compris : pas besoin de lire le moindre manuel !</p>  <p>Imaginons par exemple que vous regardez des photos avec une amie et qu'elle souhaite télécharger vos images. Grâce à la technologie NFC, il vous suffit de mettre en contact votre appareil avec son PC pour lui envoyer les photos. Cet exemple est trop simpliste ? C'est possible, mais il montre bien à quel point il est facile de partager des contenus entre des appareils.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1732.NFC-image_04E645BB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1732.NFC_2D00_image_5F00_04E645BB.png"><img title="&#39;Sur cette image, l'enceinte du Nokia 360 partage ses informations de couplage Bluetooth avec un Windows Phone" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="&#39;Sur cette image, l'enceinte du Nokia 360 partage ses informations de couplage Bluetooth avec un Windows Phone" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3566.NFC-image_thumb_38420917.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3566.NFC_2D00_image_5F00_thumb_5F00_38420917.png" width="400" height="348" /></a></p>  <p align="center">Figure 1 : sur cette image, l'enceinte du Nokia 360 partage ses informations de couplage Bluetooth    <br />avec un Windows Phone</p>  <p>Comme les technologies Bluetooth ou Wi-Fi, le NFC est un protocole sans fil standard, défini par le <a href="http://www.nfc-forum.org/home/" target="_blank">NFC Forum</a><u></u>. <u></u>Votre PC doit posséder un émetteur-récepteur NFC. De nombreux PC Windows 8 intègrent directement des émetteurs-récepteurs NFC. Si votre PC ne possède pas d'équipement NFC, vous pouvez acquérir une clé NFC qui se branche directement à votre PC.</p>  <p>La technologie NFC offre des fonctionnalités vraiment formidables. Ainsi, les utilisateurs peuvent envoyer des photos par simple contact, mettre en contact leur appareil avec une carte pour commander un repas au restaurant, ou même mettre en contact deux appareils pour coupler un appareil Bluetooth. Bien que différents les uns des autres, ces scénarios ont un point commun : le « contact », qui vise à initier l'opération. La technologie NFC est utilisée sur des appareils très divers : PC, téléphones, enceintes, casques audio, écrans sans fil, etc., pour rendre plus intuitive la connexion d'un appareil à un autre. En outre, le NFC utilise également des étiquettes RFID, ces antennes passives, légères et très peu coûteuses qui peuvent stocker une quantité non négligeable de données et qui peuvent être collées à n'importe quel objet, y compris des affiches. Par exemple, on peut dès lors imaginer acheter un ticket de cinéma en mettant en contact le téléphone avec l'affiche du film ! Dans ce cas, on parle « d'étiquette NFC ». Nous examinerons un exemple très simple de mise en contact avec une étiquette NFC, pour présenter quelques-uns des principaux concepts de l'API NFC.</p>  <p>Commençons cependant par regarder de plus près en quoi consiste la mise en contact d'appareils.</p>  <h2>Qu'est-ce qu'une mise en contact ?</h2>  <p>Qu'il s'agisse de mettre en contact des appareils pour coupler une souris Bluetooth à un ordinateur ou pour partager des photos, il est indispensable de mettre en contact les appareils de la même manière pour tous les utilisateurs. Si nous savons tous à peu près de quoi il s'agit, en pratique la plupart des utilisateurs ne savent pas quoi faire lorsqu'ils doivent mettre en contact un PC avec un autre appareil. Voici quelques recommandations en la matière, qui permettent aux utilisateurs :</p>  <ol>   <li>     <div align="center"><b>De savoir où mettre en contact les appareils</b>, en utilisant un repère visuel (parfois appelé « Approcher pour activer »), qui indique où se trouve l'antenne NFC. Le point de contact diffère selon le modèle de PC utilisé. Ainsi, pour une tablette, le point de contact peut se trouver au dos, tandis qu'il se trouvera plus vraisemblablement en face avant sur un tout-en-un. Voici à quoi ressemble le repère sur un PC Windows 8 compatible NFC :         <br /></div>     <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0830.NFC-logo_66E85720.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0830.NFC_2D00_logo_5F00_66E85720.png"><img title="Repère « Approcher pour activer »" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Repère « Approcher pour activer »" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5611.NFC-logo_thumb_3FAE0DEB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5611.NFC_2D00_logo_5F00_thumb_5F00_3FAE0DEB.png" width="200" height="147" /></a>      <p align="center">Figure 2 : repère « Approcher pour activer »</p>   </li>    <li><b>De savoir si les appareils communiquent entre eux</b> : lors de la mise en contact, les utilisateurs doivent savoir si l'opération se passe comme prévu, même s'ils ne peuvent pas voir que les données sont en cours de transfert. Ainsi, Windows émet un son lorsque des appareils sont dans le champ de portée et communiquent les uns avec les autres.</li> </ol>  <p>Windows effectue cette opération automatiquement et vous n'avez donc pas à vous en préoccuper. Pour plus d'informations sur ces éléments d'expérience utilisateur, consultez la <a href="http://msdn.microsoft.com/fr-fr/library/windows/hardware/hh770524.aspx" target="_blank">spécification Windows 8 Near Field Proximity Implementation (implémentation de la proximité en champ proche dans Windows 8)</a><u></u>. Maintenant que nous comprenons mieux le principe, examinons quelques scénarios très intéressants qui utilisent la technologie NFC.</p>  <h2>Dans quels cas utiliser la technologie NFC ? </h2>  <p>Utilisez le NFC lorsqu'un utilisateur doit sélectionner quelque chose ou quelqu'un dans votre application. Le NFC offre une solution intuitive pour sélectionner des éléments, solution qui s'avère souvent plus rapide (et plus amusante !) qu'une recherche manuelle. La mise en contact joue le rôle de déclencheur de l'expérience. Selon la nature de votre application, elle peut déclencher la réception d'une photo ou le lancement d'une liste de lecture. Une fois la mise en contact effectuée, il appartient à votre application de décider du comportement à adopter. Pour plus de simplicité, nous classons ce type d'expériences dans la catégorie « Approcher pour activer ».</p>  <p>Voici quelques exemples qui utilisent la technologie NFC pour sélectionner un élément dans une application. Grâce à une simple mise en contact, vous pouvez…</p>  <ul>   <li><u>Obtenir des informations à partir d'une affiche</u> : les <a href="http://www.nfc-forum.org/news/pr/view?item_key=2c0cb92de7d47bbbe7c99f13912b3307fc03c1c6" target="_blank">étiquettes NFC</a> sont des étiquettes RFID légères et peu coûteuses (entre 0,15 et 1 USD pièce, selon les coûts d'impression). Le fonctionnement est similaire à celui des codes QR, mais tout est plus simple et plus rapide. D'un point de vue ergonomique, il est ainsi plus facile de mettre en contact un appareil avec une étiquette plutôt que de prendre en photo un code-barres (en croisant les doigts pour que l'appareil photo trouve le bon angle). De plus en plus de fabricants intègrent des étiquettes à leurs affiches dans les lieux de passage particulièrement fréquentés (aéroports, stations de métro, arrêts de bus, etc.). Elles peuvent stocker entre 48 octets et 4 Ko de données. Vous pouvez programmer une étiquette afin qu'elle ouvre votre application sur une page spécifique. </li> </ul>  <ul>   <li><u>Échanger des coordonnées</u> : au lieu de dicter vos informations de contact à un ami en espérant qu'il ne fera pas d'erreur, il suffit de mettre en contact vos appareils pour échanger vos coordonnées. Comme dans le scénario ci-dessus, vous pouvez programmer vos coordonnées dans une carte de visite/étiquette NFC. Vous pouvez aussi échanger directement des coordonnées par le biais d'une application.</li>    <li><u>Écouter votre station de radio préférée</u> : sur le chemin du travail, en voiture ou confortablement installé dans votre canapé, vous pouvez utiliser une étiquette pour démarrer l'écoute d'une station de radio. Vous pouvez même programmer différentes stations musicales sur différentes étiquettes : une étiquette pour vos séances de jogging, une autre pour la relaxation et une dernière pour vous endormir, par exemple.</li>    <li><u>Commander un menu dans un restaurant très fréquenté</u> : au restaurant, vous devez parfois attendre très longtemps avant de pouvoir commander. Avec la technologie NFC, il suffit de mettre votre appareil en contact avec l'étiquette de votre table pour passer commande.</li>    <li><u>Jouer à un jeu multijoueur avec un ami : </u>vous pouvez facilement jouer en réseau avec un ami à un jeu multijoueur tel que Battleship, Chess ou Scrabble, en mettant en contact les appareils. Une fois la mise en contact effectuée, la connexion est maintenue en mode hors-bande, offrant une portée plus grande et un meilleur débit (Bluetooth ou Wi-Fi Direct, par exemple). </li> </ul>  <p>Maintenant que vous comprenez sans doute mieux comment utiliser la technologie NFC, amusons-nous un peu en créant une application qui utilise les API de proximité (NFC) de Windows 8.</p>  <h2>Comment mettre en œuvre la technologie NFC ? </h2>  <p>Comme vous pouvez le constater, la technologie NFC facilite de nombreuses tâches quotidiennes pour l'utilisateur final. Prenons l'exemple du réglage d'une alarme. Je suis certain que nous avons tous au moins une fois mal réglé notre réveil pour le lendemain. Lorsqu'il est tard et que nous sommes fatigués, nous n'avons pas toujours les idées claires ! Avec le NFC, il vous suffit de mettre en contact votre appareil avec une étiquette préréglée, de confirmer, puis de vous endormir tranquillement, en étant certain d'être réveillé à l'heure. Pour aider les utilisateurs à accomplir cette tâche quotidienne, vous pourriez par exemple développer une application d'alarme élémentaire permettant aux utilisateurs de configurer une alarme en utilisant une étiquette NFC. Divisions le processus en deux scénarios :</p>  <ol>   <li><u>Configuration d'une alarme <b>sur</b> l'étiquette</u> : les étiquettes NFC étant réutilisables, l'application peut permettre aux utilisateurs de programmer une alarme. Par exemple, un utilisateur peut avoir besoin de programmer différentes alarmes : une pour la semaine, une autre pour le week-end. Dans ce cas, on parle de « publication » de données sur une étiquette.</li>    <li><u>Configuration d'une alarme <b>à partir</b> de l'étiquette</u> : Dès lors qu'un utilisateur met son appareil en contact avec l'étiquette, l'application doit être ouverte pour confirmer la configuration de l'alarme. L'application peut ainsi être lancée avec un contexte ou des arguments. </li> </ol>  <p>L'API NFC offre plusieurs solutions pour parvenir au même résultat. Dans ce billet, je vais présenter la façon la plus simple de mettre en œuvre ce scénario.</p>  <p>Examinons le processus de configuration d'une alarme sur une étiquette NFC :</p>  <ol>   <li>Mario lance l'application d'alarme et définit une heure, par exemple 7 h. Pour l'instant, rien d'exceptionnel : la technologie NFC n'est pas utilisée.</li>    <li>Mario sélectionne une option permettant de « Configurer l'alarme sur une étiquette NFC ». À cet instant, l'application appelle les API NFC afin de publier des informations sur l'émetteur-récepteur NFC, en particulier une chaîne d'identificateur d'application &amp; 07:00. Les étiquettes NFC utilisent un format standardisé de messages, appelé NDEF (NFC Defined Exchange Format). Votre application n'a <b>pas</b> à gérer la mise en forme des données du message NDEF : Windows s'en occupe ! L'utilisateur peut alors mettre en contact son appareil avec l'étiquette NFC.</li>    <li>Mario met en contact l'étiquette avec le PC, et l'application confirme la programmation de l'étiquette. Au moment de la mise en contact avec l'étiquette, il est important d'indiquer à l'utilisateur que l'application a bien programmé l'étiquette. Comme nous l'avons déjà évoqué, le fait de mettre en contact un PC avec une étiquette est un concept inconnu de la plupart des utilisateurs. La confirmation permet ainsi à l'utilisateur d'être certain que l'opération s'est bien déroulée. L'application sait qu'un message a été correctement transmis en s'inscrivant auprès d'un gestionnaire de message transmis.</li> </ol>  <p>Les API NFC se trouvent dans l'espace de noms <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.proximity.aspx" target="_blank">Windows.Networking.Proximity</a>. Elles sont utilisées à partir de l'étape 2, lorsque l'utilisateur sélectionne l'option permettant de « Configurer l'alarme sur une étiquette NFC ». Tout d'abord, l'application initialise un objet de proximité. L'objet de proximité est utilisé pour indiquer quand une étiquette (ou un appareil) se trouve à l'intérieur du champ de portée ou au contraire hors de portée. Nous ajoutons ensuite le gestionnaire d'événements DeviceArrival. Ce gestionnaire détecte à quel moment l'étiquette est mise en contact avec un appareil, ce qui signifie que nous pouvons commencer à écrire des données sur l'étiquette. Il est important de signaler aux utilisateurs à quel moment vous écrivez des informations sur une étiquette, pour qu'il ne sorte pas du champ de portée. Vous pouvez utiliser le même événement pour détecter quand un appareil de proximité est mis en contact.</p>  <p>L'extrait de code ci-dessous montre comment initialiser et ajouter un gestionnaire d'événements DeviceArrival.</p>  <p><strong>JavaScript</strong></p>  <blockquote>   <div>     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> proximityDevice;<br /><br /><span style="color: rgb(0, 0, 255);">function</span> initializeProximityDevice() {<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault();<br /><br />    <span style="color: rgb(0, 0, 255);">if</span> (proximityDevice) {<br />        proximityDevice.addEventListener(<span style="color: rgb(0, 96, 128);">&quot;devicearrived&quot;</span>, proximityDeviceArrived);<br />       <br />}<br />   <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// No NFC radio on the PC, display an error message</span><br />    }<br /><br /><br /><span style="color: rgb(0, 0, 255);">function</span> proximityDeviceArrived(device) {<br />        <span style="color: rgb(0, 128, 0);">// Let the user know we’re ‘Writing to Tag’</span><br /><br />}<br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>C#</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> InitializeProximityDevice()<br />{<br /><br />Windows.Networking.Proximity.ProximityDevice proximityDevice;<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();<br /><br />    <span style="color: rgb(0, 0, 255);">if</span> (proximityDevice != <span style="color: rgb(0, 0, 255);">null</span>) {<br />        proximityDevice.DeviceArrived += ProximityDeviceArrived;<br />    <br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span><br />    {<br />        <span style="color: rgb(0, 128, 0);">// No NFC radio on the PC, display an error message</span><br />    }<br />}<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> ProximityDeviceArrived(Windows.Networking.Proximity.ProximityDevice device)<br />{<br />            <span style="color: rgb(0, 128, 0);">// Let the user know we’re ‘Writing to Tag’</span><br /><br />}<br /></pre>
  </div>
</blockquote>

<p>
  <br />Publions ensuite ces informations sur l'étiquette. L'application publie deux informations : une chaîne d'identificateur d'application, qui se compose d'un ID d'application et d'une plateforme d'application, ainsi que des arguments de lancement. Pour Windows 8, l'ID d'application est &lt;<a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.applicationmodel.packageid.familyname.aspx" target="_blank">nom de famille du package</a>&gt;!&lt;<a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211415.aspx" target="_blank">ID d'application</a>&gt; et la plateforme d'application est « Windows ». Vous devez copier la valeur d'ID d'application qui figure dans l'attribut ID de l'élément Application du manifeste de package de votre application. L'argument de lancement est « 07:00 », c'est-à-dire l'heure définie par l'utilisateur. Appelons-le <b>message</b>.</p>

<p>Si l'application fonctionne sur plusieurs plateformes, Windows vous permet de publier d'autres ID d'application et plateformes d'application. Vous pouvez ainsi mettre en contact la même étiquette avec d'autres appareils compatibles NFC, par exemple un téléphone Windows Phone 8 ! Vous trouverez des informations supplémentaires sur les <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.proximity.peerfinder.alternateidentities.aspx" target="_blank">autres ID</a> sur MSDN.</p>

<p>L'application publie les données sur l'étiquette en utilisant une méthode appelée <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh701134.aspx" target="_blank">publishBinaryMessage</a>. Cette méthode accepte trois paramètres : messageType, message, ainsi qu'une fonction messageTransmittedHandler. Définissons le paramètre messageType sur « LaunchApp:WriteTag ». Ceci indique à Windows que votre application souhaite écrire des informations sur une étiquette NFC. Le message est celui que nous avons défini plus tôt (chaîne d'identification de l'application et arguments de lancement). Nous devons stocker le message sous forme de message binaire dans un tampon. La fonction messageTransmittedHandler assure l'inscription des rappels. Ainsi, votre application sait que le message a bien été écrit sur l'étiquette. Nous utiliserons cette fonction pour signaler à l'utilisateur que le message a bien été écrit sur l'étiquette et qu'il n'est plus nécessaire que l'étiquette reste dans le champ de portée.</p>

<p>Les messages continuent à être publiés jusqu'à ce que nous appelions la fonction StopPublishingMessage ou jusqu'à ce que l'objet ProximityDevice soit publié. Dans cet exemple, nous utilisons la fonction stop. PublishBinaryMessage renvoie un ID de publication. Nous utiliserons ce même ID de publication pour arrêter la publication du message sur l'émetteur-récepteur NFC.</p>

<p>L'extrait de code suivant montre comment écrire des données sur une étiquette NFC :</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> proximityDevice;<br /><br /><span style="color: rgb(0, 0, 255);">function</span> getAlarmTime(){<br /><br />    <span style="color: rgb(0, 128, 0);">// Grab time set by the user, call this variable ‘Alarm’</span><br />    <span style="color: rgb(0, 0, 255);">return</span> Alarm;<br /><br />}<br /><br /><span style="color: rgb(0, 0, 255);">function</span> publishLaunchApp() {<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();<br /><br /><span style="color: rgb(0, 0, 255);">if</span> (proximityDevice) {<br />        <span style="color: rgb(0, 128, 0);">// The format of the app launch string is: &quot;&lt;args&gt;\tWindows\t&lt;AppName&gt;&quot;.</span><br />        <span style="color: rgb(0, 128, 0);">// The string is tab or null delimited.</span><br /><br />        <span style="color: rgb(0, 128, 0);">// The &lt;args&gt; string can be an empty string (&quot;&quot;).</span><br />        <span style="color: rgb(0, 0, 255);">var</span> launchArgs = getAlarmTime();<br /><br />        <span style="color: rgb(0, 128, 0);">// The format of the AppName is: PackageFamilyName!PRAID.</span><br />        <span style="color: rgb(0, 0, 255);">var</span> praid = <span style="color: rgb(0, 96, 128);">&quot;AlarmApp&quot;</span>; <span style="color: rgb(0, 128, 0);">// The Application Id value from your package.appxmanifest.</span><br /><br />        <span style="color: rgb(0, 0, 255);">var</span> appName = Windows.ApplicationModel.Package.current.id.familyName + <span style="color: rgb(0, 96, 128);">&quot;!&quot;</span> + praid;<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> launchAppMessage = launchArgs + <span style="color: rgb(0, 96, 128);">&quot;\tWindows\t&quot;</span> + appName;<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> dataWriter = <span style="color: rgb(0, 0, 255);">new</span> Windows.Storage.Streams.DataWriter();<br />        dataWriter.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf16LE;<br />        dataWriter.writeString(launchAppMessage);<br />        <span style="color: rgb(0, 0, 255);">var</span> launchAppPubId =<br />             proximityDevice.publishBinaryMessage(<br />                 <span style="color: rgb(0, 96, 128);">&quot;LaunchApp:WriteTag&quot;</span>, <br />                 dataWriter.detachBuffer(), <br />                 proximityWriteTagLaunchAppMessageTransmitCallback);<br />        <br />    <span style="color: rgb(0, 0, 255);">if</span> (launchAppPubId != -1) {<br />            <span style="color: rgb(0, 128, 0);">// Stop publishing the message on NFC radio</span><br />        proximityDevice.stopPublishingMessage(launchAppPubId);<br />    }<br /><br />     }<br />}<br /><br /><span style="color: rgb(0, 0, 255);">function</span> proximityWriteTagLaunchAppMessageTransmitCallback() {<br />    <span style="color: rgb(0, 128, 0);">// Inform the user that: the message has been successfully written to a tag &amp; the tag no longer needs to be in range</span><br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>C#</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Windows.Networking.Proximity.ProximityDevice proximityDevice;<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">string</span> GetAlarmTime(){<br /><br />    <span style="color: rgb(0, 128, 0);">// Grab time set by the user, call this variable ‘Alarm’</span><br />    <span style="color: rgb(0, 0, 255);">return</span> Alarm;<br />}<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> PublishLaunchApp()<br />{<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();<br /><br /><span style="color: rgb(0, 0, 255);">if</span> (proximityDevice != <span style="color: rgb(0, 0, 255);">null</span>)<br />    {<br />        <span style="color: rgb(0, 128, 0);">// The format of the app launch string is: &quot;&lt;args&gt;\tWindows\t&lt;AppName&gt;&quot;.</span><br />        <span style="color: rgb(0, 128, 0);">// The string is tab or null delimited.</span><br /><br />        <span style="color: rgb(0, 128, 0);">// The &lt;args&gt; string can be an empty string (&quot;&quot;).</span><br />        <span style="color: rgb(0, 0, 255);">string</span> launchArgs = getAlarmTime();<br /><br />        <span style="color: rgb(0, 128, 0);">// The format of the AppName is: PackageFamilyName!PRAID.</span><br />        <span style="color: rgb(0, 0, 255);">string</span> praid = <span style="color: rgb(0, 96, 128);">&quot;MyAppId&quot;</span>; <span style="color: rgb(0, 128, 0);">// The Application Id value from your package.appxmanifest.</span><br /><br />        <span style="color: rgb(0, 0, 255);">string</span> appName = Windows.ApplicationModel.Package.Current.Id.FamilyName + <span style="color: rgb(0, 96, 128);">&quot;!&quot;</span> + praid;<br /><br />        <span style="color: rgb(0, 0, 255);">string</span> launchAppMessage = launchArgs + <span style="color: rgb(0, 96, 128);">&quot;\tWindows\t&quot;</span> + appName;<br /><br />        var dataWriter = <span style="color: rgb(0, 0, 255);">new</span> Windows.Storage.Streams.DataWriter();<br />        dataWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;<br />        dataWriter.WriteString(launchAppMessage);<br />        var launchAppPubId =<br />        proximityDevice.PublishBinaryMessage(<br />            <span style="color: rgb(0, 96, 128);">&quot;LaunchApp:WriteTag&quot;</span>, dataWriter.DetachBuffer(), <br />            proximityWriteTagLaunchAppMessageTransmitCallback);<br />    <br />    <span style="color: rgb(0, 0, 255);">if</span> (launchAppPubId!= -1)<br />    {<br />        proximityDevice.StopPublishingMessage(launchAppPubId);<br />    <span style="color: rgb(0, 128, 0);">// Stop publishing the message on NFC radio</span><br />    }<br /><br />    }<br />}<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> proximityWriteTagLaunchAppMessageTransmitCallback(<br />    Windows.Networking.Proximity.ProximityDevice sender,<br />    <span style="color: rgb(0, 0, 255);">long</span> messageId)<br />{<br />        <span style="color: rgb(0, 128, 0);">// Inform the user that: the message has been successfully written to a tag &amp; the tag no longer needs to be in range</span><br />}<br /></pre>
  </div>
</blockquote>

<br />C'est tout ! Vous savez maintenant comment écrire des données sur une étiquette NFC à partir d'une application du Windows Store. Puisque la procédure est relativement simple, passons au scénario suivant et configurons une alarme <b>à partir</b> de l'étiquette. Examinons le processus permettant de lire une alarme à partir d'une étiquette NFC : 

<ol>
  <li>Mario lit son écran d'accueil, rédige un courrier électronique, joue à un jeu ou utilise Windows, et réalise qu'il doit régler une alarme pour lundi matin. Il attrape son étiquette « Alarme semaine » et la met en contact avec son PC. Un toast s'affiche pour l'inviter à lancer son application Alarme. Pour le moment, Windows s'occupe de tout et votre application n'a pas encore été utilisée.</li>

  <li>Mario accepte. Votre application démarre et affiche un écran « Confirmer l'alarme ? » qui indique 7 h. Une fois le toast accepté par Mario, Windows transmet les arguments de lancement (comme ci-dessus) à votre application lors de l'activation. Nous désignons cette opération par le terme « lancement contextuel ». Cela revient à ouvrir votre application sur une page spécifique.</li>

  <li>Mario configure l'alarme. Cette opération est totalement classique et n'implique pas la technologie NFC.</li>
</ol>

<p>Il est relativement simple d'obtenir les arguments de lancement auprès de l'étiquette NFC. L'application doit gérer un lancement contextuel à partir d'une étiquette NFC. Le lancement contextuel revient à ouvrir votre application sur une page spécifique. Nos arguments de lancement configurent l'alarme sur 7 h et votre application utilise cette information pour afficher l'alarme proposée. En outre, si jamais votre application n'est pas installée sur le PC, Windows invite Mario à installer votre application à partir du Windows Store, le tout de façon automatisée !</p>

<p>L'extrait de code suivant montre comment mettre en œuvre le lancement contextuel.</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">app.onactivated = <span style="color: rgb(0, 0, 255);">function</span> (args) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (args.detail.kind === activation.ActivationKind.launch) {<br />        <span style="color: rgb(0, 0, 255);">if</span> (args.detail.arguments == <span style="color: rgb(0, 96, 128);">&quot;Windows.Networking.Proximity.PeerFinder:StreamSocket&quot;</span>) {<br />            <span style="color: rgb(0, 128, 0);">//do nothing here.</span><br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span> {<br />    <span style="color: rgb(0, 128, 0);">// Use args.detail.arguments to parse out ’07.00’ string, and display to the user</span><br />        }<br /><br />        args.setPromise(WinJS.UI.processAll());<br />    }<br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>C#</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">async <span style="color: rgb(0, 0, 255);">protected</span> <span style="color: rgb(0, 0, 255);">override</span> <span style="color: rgb(0, 0, 255);">void</span> OnLaunched(LaunchActivatedEventArgs args)<br />        {<br />            <span style="color: rgb(0, 0, 255);">if</span> (args.Arguments == <span style="color: rgb(0, 96, 128);">&quot;Windows.Networking.Proximity.PeerFinder:StreamSocket&quot;</span>)<br />            {<br />                _isLaunchedByTap = <span style="color: rgb(0, 0, 255);">true</span>;<br />            }<br />            <span style="color: rgb(0, 0, 255);">else</span><br />            {<br /><span style="color: rgb(0, 128, 0);">// Use args.Arguments to parse out ’07.00’ string, and display to the user</span><br /><br />            }<br />            Window.Current.Activate();<br />        }<br /></pre>
  </div>
</blockquote>

<p>
  <br />Tout cela suffit pour que votre application prenne en charge la lecture des étiquettes NFC et l'écriture sur ces étiquettes : plutôt simple, pour un scénario vraiment innovant ! Avant de conclure, évoquons une bonne pratique : la gestion des erreurs.</p>

<h2>Gestion des erreurs</h2>

<p>Votre application est susceptible de rencontrer un certain nombre d'erreurs courantes.</p>

<ul>
  <li>L'étiquette mise en contact n'est pas au format NDEF. Windows 8 ne prend pas en charge la conversion automatique des étiquettes au format NDEF. Par conséquent, vous devez télécharger et installer un outil de mise en forme NDEF.</li>

  <li>L'étiquette mise en contact est en lecture seule. Certaines étiquettes NFC peuvent être verrouillées en lecture seule (comme ces bonnes vieilles <a href="http://fr.wikipedia.org/wiki/Video_Home_System" target="_blank">cassettes VHS</a>).</li>

  <li>L'étiquette mise en contact est trop petite et ne peut pas stocker toutes les données.</li>

  <li>Le PC de l'utilisateur ne possède pas d'émetteur-récepteur NFC. Comme je l'ai expliqué au début de ce billet, la technologie NFC est encore émergente, mais son adoption à grande échelle est en cours. Pour savoir si un PC prend en charge les transferts de proximité, utilisez la méthode ProximityDevice.getDefault(). Elle renvoie la valeur NULL si aucun émetteur-récepteur radio n'est installé.</li>
</ul>

<h2>Une technologie aussi amusante qu'intuitive</h2>

<p>La technologie NFC est enfin à la portée du grand public : Windows possède l'écosystème requis et une expérience utilisateur complète extrêmement bien conçue. Le potentiel de cette technologie est immense et devrait rendre les applications et les expériences utilisateur des appareils incroyablement interactives. Son fonctionnement est amusant et intuitif. </p>

<p>Le NFC est un domaine très vaste et nous publierons probablement d'autres billets de blog pour présenter d'autres fonctionnalités NFC mises en œuvre par des développeurs sur Windows 8.</p>

<p>Pour plus d'informations sur le NFC et les transferts de proximité, consultez les ressources ci-dessous.</p>

<h2>Ressources</h2>

<div align="center">
  <table class="b8table" cellspacing="0" cellpadding="3" width="298" align="center" border="0"><tbody>
      <tr>
        <td valign="top" width="197">
          <p><strong>Lien</strong></p>
        </td>

        <td valign="top" width="99">
          <p><strong>Type</strong></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><u><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465215.aspx" target="_blank">Recommandations sur le développement avec la fonctionnalité de proximité</a></u></p>
        </td>

        <td valign="top" width="99">
          <p>Document</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br241250.aspx" target="_blank">API de proximité</a></p>
        </td>

        <td valign="top" width="99">
          <p>Document</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh967765.aspx" target="_blank">Test de la fonctionnalité de proximité et résolution des problèmes connexes dans les applications</a></p>
        </td>

        <td valign="top" width="99">
          <p>Document</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465223.aspx" target="_blank">Publication et abonnement (plus de détails)</a></p>
        </td>

        <td valign="top" width="99">
          <p>Document</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Proximity-Sample-88129731" target="_blank">Exemple d'application de proximité</a></p>
        </td>

        <td valign="top" width="99">
          <p>Exemple</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://social.msdn.microsoft.com/Forums/fr-fr/category/windowsapps" target="_blank">Une question sur les fonctions de proximité ? Posez-la ici !</a></p>
        </td>

        <td valign="top" width="99">
          <p>Forum</p>
        </td>
      </tr>
    </tbody></table>
</div>

<p>Merci !</p>

<p>Priya Dandawate 
  <br />Chef de projet, Appareils et mise en réseau</p>

<p>Avec la participation de Max Morris, Marzena Makuta, Mike Loholt, Jake Sabulsky et Vishal Mhatre</p>

<!-- Title: “Développer une application innovante grâce au NFC” Tags: “partage, NFC, Near Field Communication, partage de fichiers, couplage Bluetooth, partage de données” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Créer des applications Windows Store connectées</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/crer-des-applications-windowsstore-connectes</link>
      <pubDate>Wed, 17 Apr 2013 13:56:03 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/04/17/crer-des-applications-windowsstore-connectes/</guid>
      <description><![CDATA[De plus en plus, nous sommes entourés de nombreux appareils connectés à un réseau. Même les...]]></description>
      <content:encoded><![CDATA[<div class="postcontent">  <p>De plus en plus, nous sommes entourés de nombreux appareils connectés à un réseau. Même les dernières générations de réfrigérateurs et de machines à laver peuvent aussi se connecter à Internet et aux réseaux domestiques. Sans surprise, l'utilisateur final attend de ses applications qu'elles soient elles aussi connectées. Ces « applications connectées » exploitent les derniers contenus du Web : médias sociaux, médias numériques, blogs et autres types de contenus. Le développement d'applications connectées est désormais la norme. Néanmoins, il est parfois difficile de résoudre certains problèmes courants : perte de connectivité réseau, coûts liés à une connexion réseau limitée, problèmes de performances, etc. Avec Windows 8, il est plus facile que jamais de développer une application connectée. </p>  <p>Dans ce billet, nous dévoilons quelques conseils utiles qui vous aideront à proposer aux utilisateurs de vos applications du Windows Store une expérience connectée, rapide, fluide et sans la moindre complication : </p>  <ul>   <li>Sélectionner l'API adaptée à vos scénarios</li>    <li>Choisir les fonctionnalités réseau adéquates</li>    <li>Adapter le comportement de l'application aux connexions réseau limitées</li>    <li>Réagir aux changements d'état du réseau</li>    <li>Mettre le contenu en cache pour plus de fluidité</li> </ul>  <p>Examinons en détail chacun de ces conseils.</p>  <h2>Sélectionner l'API adéquate</h2>  <p>Lorsque vous construisez une maison, vous devez disposer des bons outils. Vous avez besoin d'un marteau pour enfoncer les clous, d'une scie pour couper des panneaux et d'un tournevis pour fixer vos vis. De la même manière, lorsque vous développez une application du Windows Store connectée, vous devez utiliser les API de réseau adéquates. Windows 8 offre plusieurs API de réseau que votre application peut exploiter pour communiquer avec d'autres ordinateurs et appareils, via Internet ou des réseaux privés. Pour commencer, vous devez déterminer de quelles fonctionnalités réseau votre application a besoin. </p>  <p>Le scénario de mise en réseau le plus courant consiste à accéder à un site Web pour récupérer ou stocker des informations. Un jeu utilisant un site Web pour stocker les informations relatives aux utilisateurs et leurs scores fait partie des exemples les plus simples. De façon plus complexe, une application peut aussi se connecter à un service Web REST et utiliser une bibliothèque fournie par le service Web pour accéder à des informations ou les stocker. Windows 8 possède plusieurs API qui se connectent aux services Web et aux sites Web. Grâce à ces API, votre application peut accéder aux services Web compatibles REST ou envoyer des commandes de base du protocole HTTP (GET et POST, par exemple) à un serveur Web. Dans le cas d'un accès Web, l'API à utiliser dépend du langage de développement de l'application :</p>  <ul>   <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh453379.aspx" target="_blank">XMLHTTPRequest</a> et <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229787.aspx" target="_blank">WinJS.xhr</a> : applications écrites en JavaScript et HTML.</li>    <li><a href="http://msdn.microsoft.com/fr-fr/library/system.net.http.httpclient.aspx" target="_blank">HttpClient</a> : applications écrites en C# ou en Visual Basic .NET et XAML.</li>    <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh831163.aspx" target="_blank">XML HTTP Request 2</a> (IXHR2) : applications écrites en C++ et XAML.</li> </ul>  <p>Le code ci-dessous montre comment réaliser une opération de requête/réponse élémentaire à l'aide d'un service Web REST. Dans ce cas, le service Web peut exécuter un script ASP.NET sur le serveur Web.</p>  <p><strong>JavaScript</strong></p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> makeXHRCall() {<br />    WinJS.xhr({ uri: <span style="color: rgb(0, 96, 128);">&quot;http://www.microsoft.com/en-us/default.aspx” }).done(<br />        function onComplete(result) {<br />            print(result.responseText);<br />        },<br />        function onError(err) {<br />            print(&quot;</span>Error: &quot; + err.responseText);<br />        });<br />}<br /></pre>
  </div>
</blockquote>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">private</span> async <span style="color: rgb(0, 0, 255);">void</span> MakeHttpCall()<br />{<br />    HttpClient httpClient = <span style="color: rgb(0, 0, 255);">new</span> HttpClient();<br />    <span style="color: rgb(0, 0, 255);">try</span> {<br />        <span style="color: rgb(0, 0, 255);">string</span> response = await httpClient.GetStringAsync(<span style="color: rgb(0, 96, 128);">&quot;http://www.microsoft.com/en-us/default.aspx&quot;</span>);<br />    }<br />    <span style="color: rgb(0, 0, 255);">catch</span> (Exception) {<br />        <span style="color: rgb(0, 128, 0);">// Handle exception.</span><br />    }<br />}<br /></pre>

    <br /></div>
</blockquote>

<p>Pour plus d'informations sur <b>WinJS.xhr</b>, voir<u> </u><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh761502.aspx" target="_blank">Connexion aux services Web (applications du Windows Store en JavaScript et HTML)</a>. Pour plus d'informations sur <b>HttpClient</b>, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/xaml/hh781239.aspx" target="_blank">Démarrage rapide : connexion à l'aide de HttpClient (applications du Windows Store en C#/VB/C++ et XAML)</a> et l'<a href="http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664" target="_blank">exemple HttpClient</a>.</p>

<p>Autre scénario courant de mise en réseau : les opérations de téléchargement ou de chargement de fichiers qui peuvent être relativement longues. Il peut par exemple s'agir d'une application d'appareil photo ou de galerie qui doit charger ou télécharger des albums photo auprès d'un service Web. Ces transferts pouvant prendre du temps, il est impensable d'obliger l'utilisateur à patienter jusqu'à la fin du transfert. L'API <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.backgroundtransfer.aspx" target="_blank">Windows.Networking.BackgroundTransfer</a> offre la possibilité de télécharger ou de charger des fichiers même lorsque votre application n'est plus en cours d'exécution. L'application lance le transfert lorsqu'elle est exécutée au premier plan, puis Windows 8 poursuit le transfert en arrière-plan même lorsque l'application n'est plus en cours d'exécution.</p>

<p>L'accès à du contenu syndiqué fait partie des scénarios plus spécialisés. L'API <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.web.syndication.aspx" target="_blank">Windows.Web.Syndication</a> peut récupérer des flux au format RSS ou Atom. Par ailleurs, l'API <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.web.atompub.aspx" target="_blank">Windows.Web.AtomPub</a> permet à une application de publier des données dans différents formats AtomPub.</p>

<p>Pour les scénarios dans lesquels un protocole de haut niveau spécifique n'est pas disponible via une API, Windows Runtime prend également en charge les sockets TCP et UDP (ainsi que la multidiffusion). L'API <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.sockets.aspx" target="_blank">Windows.Networking.Sockets</a> fournit un socket <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.sockets.streamsocket.aspx" target="_blank">StreamSocket</a> (TCP) et un socket <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.sockets.datagramsocket.aspx" target="_blank">DatagramSocket</a> (UDP), pour vous permettre d'implémenter d'autres protocoles de plus haut niveau.</p>

<p><b>Remarque : </b>Windows 8 possède un nouveau type de socket appelé <i>WebSocket</i>. Pour obtenir plus d'informations sur les sockets WebSocket et pour savoir dans quels cas les utiliser, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh761442.aspx" target="_blank">Connexion à l'aide de sockets WebSocket</a>.</p>

<p>Le tableau ci-dessous contient une liste plus complète des fonctionnalités réseau prises en charge, ainsi que des liens permettant d'accéder à des informations complémentaires.</p>

<div align="center">  <table class="b8table" cellspacing="0" cellpadding="3" align="center" border="0"><tbody>
      <tr>
        <td valign="top" width="217">
          <p align="center"><b>API</b><b></b></p>
        </td>

        <td valign="top" width="221">
          <p align="center"><b>Fonctionnalité</b><b></b></p>
        </td>

        <td valign="top" width="145">
          <p align="center"><b>Exemples</b><b></b></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <ul>
            <li>
              <div align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.web.syndication.aspx" target="_blank">Windows.Web.Syndication</a></b><b></b></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.web.atompub.aspx" target="_blank">Windows.Web.AtomPub</a></b><b></b></div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Récupération de flux au format RSS ou Atom (plusieurs versions compatibles). Ces API facilitent l'implémentation de la prise en charge de formats plus récents tels qu'OData. Windows Runtime prend également en charge le protocole Atom Publishing Protocol, ce qui lui permet de publier des collections Atom. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh452973.aspx/" target="_blank">Accès et gestion du contenu syndiqué</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Syndication-sample-07ef6b0d" target="_blank">Exemple de syndication</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/AtomPub-sample-c1fcdc8e" target="_blank">Exemple AtomPub</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Lecteurs RSS</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <p align="left"></p>

          <p align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.backgroundtransfer.aspx" target="_blank">Windows.Networking.BackgroundTransfer</a></b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Téléchargement et chargement du contenu sans interruption, à moindre coût et avec possibilité de reprise, même lorsque l'application appelante n'est pas au premier plan. Cette API prend en charge le transfert de contenu via les protocoles HTTP, HTTPS et FTP. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh452979.aspx" target="_blank">Transfert de données en arrière-plan</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Background-Transfer-Sample-d7833f61" target="_blank">Exemple de transfert en arrière-plan</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">SkyDrive</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Vidéo Xbox</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh453379.aspx" target="_blank">XMLHTTPRequest</a></b><b> (JavaScript</b><b>) </b></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br229787.aspx" target="_blank">WinJS.xhr</a></b><b> </b><b>(JavaScript)</b></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/system.net.http.httpclient.aspx" target="_blank">HttpClient</a></b><b> </b><b>(C#)</b></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh831163.aspx">XML HTTP Request 2</a></b><b> (IXHR2)</b><b> </b><b>(C++)</b><b></b></div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Interaction avec les services Web REST et d'autres protocoles HTTP. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh761502.aspx" target="_blank">Connexion aux services Web</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/XHR-handling-navigation-50d03a7a" target="_blank">XHR, gestion des erreurs de navigation et exemple de schémas d'URL</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664" target="_blank">Exemple HttpClient</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Bing Cartes</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <p align="left"></p>

          <p align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.proximity.aspx" target="_blank">Windows.Networking.Proximity</a></b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Détection de la proximité entre deux appareils, après quoi les applications peuvent déclencher une communication réseau entre elles à l'aide d'API de socket. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465229.aspx" target="_blank">Prise en charge de la fonctionnalité de proximité et du geste tactile</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Proximity-Sample-88129731" target="_blank">Exemple de proximité</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Jeux</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Applications de collaboration</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <p align="left"></p>

          <p align="left"><b><a href="http://msdn.microsoft.com/library/windows/apps/BR207928" target="_blank">Windows.Storage.Pickers</a></b><b></b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Communication avec des partages de fichiers distants. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh464959.aspx" target="_blank">Accès aux données et aux fichiers</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/File-picker-sample-9f294cba" target="_blank">Exemple de sélecteur de fichiers</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Xbox Music</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Photos</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <p align="left"></p>

          <p align="left"><b><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.sockets.aspx" target="_blank">Windows.Networking.Sockets</a></b><b></b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Connexion à un service qui utilise un protocole non pris en charge par les API déjà mentionnées, tel que SMTP, MAPI ou telnet, ou connexion à un autre appareil situé sur le même réseau local. Également utilisée pour les applications qui nécessitent une sémantique similaire à celle d'un socket (communication asynchrone et bidirectionnelle) pour la connexion via le Web (y compris via des proxys HTTP) à un nouveau service. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh452977.aspx" target="_blank">Connexion à l'aide de sockets</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/StreamSocket-Sample-8c573931" target="_blank">Exemple de socket StreamSocket</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/DatagramSocket-sample-76a7d82b" target="_blank">Exemple de socket DatagramSocket</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Connecting-with-WebSockets-643b10ab" target="_blank">Exemple de connexion à l'aide de sockets WebSocket</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/site/search?query=controlchanneltrigger&amp;f%5B0%5D.Value=controlchanneltrigger&amp;f%5B0%5D.Type=SearchText&amp;ac=3" target="_blank">Exemples ControlChannelTrigger</a></div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Lync, tableau blanc collaboratif ou stock-picking</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="217">
          <p align="left"></p>

          <p align="left"><b><a href="http://msdn.microsoft.com/library/windows/apps/BR241587" target="_blank">Windows.Storage.ApplicationData</a></b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="221">
          <p align="left"></p>

          <p align="left">Windows 8 convertit automatiquement certaines données d'applications entre les appareils des utilisateurs. L'itinérance des données des applications est utile lorsque l'utilisateur possède plusieurs appareils (un PC au travail et une tablette à son domicile, par exemple) et il installe l'application sur ces différents appareils. 
            <br />Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh465094.aspx" target="_blank">Recommandations en matière de données d'application itinérantes</a>.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="145">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left"><a href="http://go.microsoft.com/fwlink/p/?linkid=231478" target="_blank">Exemple de données d'application</a></div>
            </li>
          </ul>
        </td>
      </tr>
    </tbody></table>
</div>

<h2>Choisir les fonctionnalités réseau adéquates</h2>

<p>L'isolement réseau fait partie du modèle de sécurité utilisé par Windows 8. Windows détecte de façon active les limites du réseau et met en application des restrictions d'accès réseau pour l'isolement réseau. Déployées correctement, ces fonctionnalités vous aident à protéger les utilisateurs et les applications contre les attaques malveillantes.</p>

<p>Les applications doivent déclarer des fonctionnalités d'isolement réseau pour pouvoir définir le périmètre de l'accès réseau. En l'absence de déclaration de ces fonctionnalités, votre application n'aura pas accès aux ressources réseau. Pour en savoir plus sur la manière dont Windows applique l'isolement réseau pour les applications, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/Hh770532.aspx" target="_blank">Comment définir les fonctionnalités réseau</a>. </p>

<p>Sachez que vous ne pouvez pas utiliser la mise en réseau comme mécanisme de communication entre processeurs, entre une application du Windows Store et une application de bureau sur un même appareil. Par conséquent, vous ne pouvez pas utiliser des adresses de bouclage IP dans une application du Windows Store. Il existe quelques exceptions à cette règle, prévues à des fins de développement. Elles permettent d'utiliser des adresses de bouclage IP dans le débogueur Visual Studio. Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/Hh780593.aspx" target="_blank">Comment activer le bouclage et résoudre les problèmes liés à l'isolement réseau</a>.</p>

<p>Les requêtes d'accès réseau se répartissent en deux catégories : </p>

<ol>
  <li><b>Requêtes sortantes initiées par le client</b> : votre application joue le rôle de client et initie un accès réseau en envoyant une requête réseau initiale à un ordinateur distant (un serveur, en général). L'application envoie une ou plusieurs requêtes au serveur, puis le serveur renvoie une ou plusieurs réponses. Par exemple, le trafic entre une application de client Web et un serveur Web entre dans cette catégorie.</li>

  <li><b>Requêtes sortantes non sollicitées</b> : votre application joue le rôle de serveur réseau et écoute les requêtes réseau entrantes issues d'un ordinateur distant. L'ordinateur distant initie un accès réseau en envoyant une requête initiale à votre application, qui joue le rôle de serveur. L'ordinateur distant envoie une ou plusieurs requêtes à votre application, qui renvoie une ou plusieurs réponses à l'ordinateur distant. Par exemple, une application jouant le rôle de serveur multimédia entre dans cette catégorie.</li>
</ol>

<p>Suivez le principe des privilèges minimum et ajoutez uniquement les fonctionnalités dont votre application a besoin. Ainsi, votre application peut n'avoir besoin que de requêtes sortantes initiées par le client ou au contraire pouvoir recevoir des requêtes entrantes non sollicitées. Certaines applications ont aussi besoin d'accéder aux informations et aux certificats de l'utilisateur pour s'authentifier sur un réseau. </p>

<p>Le tableau ci-dessous détaille les fonctionnalités d'isolement réseau et les autres fonctionnalités similaires souvent requises par les applications connectées. Les trois premières correspondent aux fonctionnalités d'isolement réseau principales que les applications connectées utilisent. En fait, votre application connectée doit activer au moins l'une de ces trois premières fonctionnalités. Les autres entrées de la table correspondent à des fonctionnalités complémentaires souvent requises par certaines applications connectées.</p>

<p> </p>

<div align="center">
  <table class="b8table" cellspacing="0" cellpadding="3" width="612" align="center" border="0"><tbody>
      <tr>
        <td valign="top" width="146">
          <p><b>Fonctionnalité réseau</b></p>
        </td>

        <td valign="top" width="273">
          <p><b>Description</b></p>
        </td>

        <td valign="top" width="191">
          <p><b>Exemples d'applications</b></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="146">
          <p align="left">Internet (client)</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="273">
          <p align="left"></p>

          <p align="left">Fournit un accès sortant à Internet et aux réseaux situés dans des lieux publics (aéroports, cafés, etc.). La plupart des applications nécessitant un accès à Internet doivent déclarer cette fonctionnalité.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="191">
          <p align="left">        </p>

          <ul>
            <li>
              <div align="left">Lecteurs RSS</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Réseaux sociaux</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Jeux</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="146">
          <p align="left"></p>

          <p align="left">Internet (client et serveur)</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="273">
          <p align="left"></p>

          <p align="left">Fournit à la fois un accès entrant et un accès sortant à Internet et aux réseaux situés dans des lieux publics (aéroports, cafés, etc.). L'accès entrant aux ports critiques est toujours bloqué. Cette fonctionnalité est un sur-ensemble de la fonctionnalité Internet (client). Il n'est pas nécessaire de déclarer les deux.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="191">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Applications P2P</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Jeux multijoueurs détectant les joueurs par le biais d'une multidiffusion.</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="146">
          <p align="left"></p>

          <p align="left">Réseaux privés (client et serveur)</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="273">
          <p align="left"></p>

          <p align="left">Fournit un accès réseau entrant et sortant dans les liens privés approuvés par l'utilisateur. Il s'agit généralement de réseaux domestiques ou de réseaux d'entreprise. L'accès entrant aux ports critiques est toujours bloqué.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="191">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Applications qui accèdent au contenu d'un NAS (Network Attached Storage)</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Applications métier</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Jeux multijoueurs détectant les joueurs par le biais d'une multidiffusion sur un réseau privé (réseau domestique ou réseau d'entreprise).</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="146">
          <p align="left"></p>

          <p align="left">Proximité</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="273">
          <p align="left"></p>

          <p align="left">Fonctionnalité requise pour la communication en champ proche avec des appareils. Permet aux applications d'accéder au réseau pour se connecter à un appareil situé à proximité, en demandant à l'utilisateur d'envoyer ou d'accepter une invitation.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="191">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Jeux multijoueurs dont les joueurs sont très proches les uns des autres<i></i></div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="146">
          <p align="left"></p>

          <p align="left">Authentification en entreprise</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="273">
          <p align="left"></p>

          <p align="left">Offre la possibilité de se connecter aux ressources intranet d'entreprise qui nécessitent des informations d'identification de domaine.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="191">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Applications métier</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="146">
          <p align="left"></p>

          <p align="left">Certificats utilisateur partagés</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="273">
          <p align="left"></p>

          <p align="left">Offre la possibilité d'accéder aux certificats logiciels et matériels (certificats sur carte à puce, par exemple) pour valider l'identité d'un utilisateur. Lorsque les API associées sont appelées au moment de l'exécution, l'utilisateur doit entreprendre une action (insérer une carte, sélectionner un certificat, etc.). </p>

          <p align="left"></p>
        </td>

        <td valign="top" width="191">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Applications de réseau privé virtuel</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">Applications métier</div>
            </li>
          </ul>
        </td>
      </tr>
    </tbody></table>
</div>

<p>Servez-vous de cette liste pour vérifier que l'isolement réseau est configuré dans votre application :</p>

<ul>
  <li>Déterminez le sens de l'accès réseau dont votre application a besoin : requêtes sortantes initiées par le client, requêtes entrantes non sollicitées ou les deux à la fois.</li>

  <li>Déterminez le type de ressources réseau avec lesquelles votre application communiquera : ressources approuvées sur un réseau domestique ou un réseau d'entreprise, ressources hébergées sur Internet ou les deux à la fois. </li>

  <li>Configurez les fonctionnalités minimales requises pour l'isolement réseau dans le manifeste de l'application. Pour cela, vous pouvez utiliser le <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br230259.aspx" target="_blank">concepteur de manifeste</a> de Microsoft Visual Studio 2012 ou les <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br211477.aspx" target="_blank">ajouter manuellement</a>.</li>

  <li>Déployez et exécutez votre application afin de la tester en utilisant les outils d'isolement réseau fournis pour le dépannage. Pour plus d'informations, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/Hh780593.aspx" target="_blank">Comment activer le bouclage et résoudre les problèmes liés à l'isolement réseau</a>.</li>
</ul>

<p>La capture d'écran ci-dessous montre comment activer les fonctionnalités d'isolement réseau à l'aide du <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/br230259.aspx" target="_blank">concepteur de manifeste</a> de Microsoft Visual Studio 2012.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7268.app-manifest-design_47107BBF.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7268.app_2D00_manifest_2D00_design_5F00_47107BBF.png"><img title="Sélectionnez les fonctionnalités réseau dans le fichier package.appxmanifest de votre application dans Visual Studio 2012" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Sélectionnez les fonctionnalités réseau dans le fichier package.appxmanifest de votre application dans Visual Studio 2012" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7752.app-manifest-design_thumb_5EC7B325.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7752.app_2D00_manifest_2D00_design_5F00_thumb_5F00_5EC7B325.png" width="600" height="318" /></a></p>

<p align="center"><em>Sélectionnez les fonctionnalités réseau dans le fichier package.appxmanifest de votre application dans Visual Studio 2012</em></p>

<h2>Adapter le comportement de l'application aux connexions réseau limitées</h2>

<p>Réfléchissez à la dernière fois que vous avez atteint les limites de votre forfait données ou que vous avez voyagé à l'étranger. Dans ces situations, personnellement, je finis par utiliser mon appareil et les applications avec une extrême précaution pour empêcher une lourde facturation réseau. </p>

<p>Windows 8 résout ce problème pour l'utilisateur en permettant aux applications de surveiller les ressources réseau disponibles et d'adopter le comportement adéquat sur les connexions réseau limitées. Pour que l'utilisateur ait toujours plus confiance dans vos applications, vous pouvez permettre à votre application de savoir quand une connexion peut engendrer des coûts et adapter son comportement pour réduire ou éliminer ces coûts.</p>

<p>L'API <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.aspx" target="_blank">Windows.Networking.Connectivity</a> fournit des informations sur le type et le coût d'une connexion réseau limitée. Ainsi, votre application peut déterminer s'il est préférable d'utiliser les ressources réseau normalement, de façon restrictive, ou de poser la question à l'utilisateur. </p>

<p>Une classe <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectionprofile.aspx" target="_blank">ConnectionProfile</a> représente une connexion réseau. Votre application peut utiliser la classe <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> d'une classe <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectionprofile.aspx" target="_blank">ConnectionProfile</a> pour déterminer si son comportement doit ou non être adapté. La propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> indique le type de connexion réseau. Il existe quatre valeurs possibles :</p>

<ul>
  <li><b>Unrestricted (sans restriction)</b> : cette connexion réseau peut être utilisée de façon illimitée. Aucuns frais ne sont facturés en fonction de l'utilisation ou de la capacité.</li>

  <li><b>Fixed (fixe)</b> : cette connexion réseau peut être utilisée de façon illimitée jusqu'à une certaine limite.</li>

  <li><b>Variable (variable)</b> : cette connexion réseau est facturée selon la consommation (en octets).</li>

  <li><b>Unknown (inconnu)</b> : les informations de tarification de cette connexion réseau ne sont pas disponibles.</li>
</ul>

<p>Plusieurs autres propriétés booléennes de la classe <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> fournissent d'autres informations. </p>

<ul>
  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.roaming.aspx" target="_blank">Roaming</a> : la connexion est établie avec un réseau situé à l'extérieur du périmètre domestique.</li>

  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.approachingdatalimit.aspx" target="_blank">ApproachingDataLimit</a> : la connexion approche de la limite d'utilisation spécifiée dans le forfait.</li>

  <li><a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.overdatalimit.aspx" target="_blank">OverDataLimit</a> : la connexion a dépassé la limite d'utilisation spécifiée par le forfait.</li>
</ul>

<p>Vous pouvez faire en sorte que votre application réagisse aux conditions indiquées par ces propriétés. Chaque fois qu'une connexion a la valeur <b>Roaming</b>, les coûts de transfert de données associés à l'utilisateur du réseau peuvent être élevés. Lorsque la valeur de la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> est <b>Variable</b>, l'application utilise une connexion réseau limitée : l'utilisateur est facturé en fonction de la quantité de données envoyées ou reçues sur le réseau. Lorsque la valeur de la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> est <b>Fixed</b>, mieux vaut limiter les transferts de données si l'utilisateur a déjà dépassé la limite ou s'en approche. </p>

<p>En utilisant ces informations, une application peut respecter ces recommandations afin de décider comment utiliser au mieux les ressources réseau.</p>

<div align="center">
  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <p align="left"></p>

  <table class="b8table" cellspacing="0" cellpadding="3" align="center" border="0"><tbody>
      <tr>
        <td valign="top" width="97">
          <p><b>Comportement</b></p>
        </td>

        <td valign="top" width="150">
          <p><b>Coût de la connexion</b></p>
        </td>

        <td valign="top" width="168">
          <p><b>Recommandations relatives à l'application</b></p>
        </td>

        <td valign="top" width="175">
          <p><b>Exemples</b></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="97">
          <p align="left">Normal</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="150">
          <p align="left"></p>

          <p align="left">La valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> est<b>Unrestricted</b> ou <b>Unknown</b>, et la valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> n'est pas <b>Roaming</b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="168">
          <p align="left"></p>

          <p align="left">L'application n'applique aucune restriction. Elle considère la connexion comme étant de type <b>Unlimited</b>, c'est-à-dire illimitée en termes de coût, et non limitée par l'utilisation ou la capacité.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="175">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Un lecteur multimédia peut lire un film HD en entier.</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">L'application peut télécharger des fichiers sans appliquer de limite ni afficher un message destiné à l'utilisateur.</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="97">
          <p align="left"></p>

          <p align="left">Prudent</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="150">
          <p align="left"></p>

          <p align="left">La valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> est <b>Fixed</b> ou <b>Variable</b>, et la valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> n'est pas <b>Roaming</b> ni <b>OverDataLimit</b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="168">
          <p align="left"></p>

          <p align="left">L'application applique des restrictions pour optimiser l'utilisateur du réseau, afin de traiter les opérations sur les connexions réseau limitées.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="175">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">Un lecteur multimédia peut lire des films en basse résolution.</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">L'application peut retarder les téléchargements qui ne sont pas indispensables.</div>
            </li>

            <p align="left"></p>
          </ul>

          <p align="left"></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="97">
          <p align="left"></p>

          <p align="left">Sur demande</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="150">
          <p align="left"></p>

          <p align="left">La valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> est <b>Roaming</b> ou <b>OverDataLimit</b></p>

          <p align="left"></p>
        </td>

        <td valign="top" width="168">
          <p align="left"></p>

          <p align="left">L'application gère les cas exceptionnels où le coût de l'accès réseau est vraiment supérieur à celui du forfait.</p>

          <p align="left"></p>
        </td>

        <td valign="top" width="175">
          <p align="left"></p>

          <ul>
            <p align="left"></p>

            <li>
              <div align="left">L'application demande à l'utilisateur si elle peut accéder au réseau.</div>
            </li>

            <p align="left"></p>

            <li>
              <div align="left">L'application suspend l'ensemble des activités d'arrière-plan de transfert de données via le réseau.<i></i></div>
            </li>
          </ul>
        </td>
      </tr>
    </tbody></table>
</div>

<p>Cet exemple de code vérifie le coût de la connexion et renvoie des suggestions de comportement adéquat. </p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> CostGuidance = { Normal: 0, Conservative: 1, OptIn: 2 };<br /><span style="color: rgb(0, 128, 0);">// GetCostGuidance returns an object with a Cost (with value of CostGuidance), </span><br /><span style="color: rgb(0, 128, 0);">// CostName (a string) and Reason, which says why the cost is what it is.</span><br /><span style="color: rgb(0, 0, 255);">function</span> GetCostGuidance() <br />{<br />    <span style="color: rgb(0, 0, 255);">var</span> connectionCost = Windows.Networking.Connectivity.NetworkInformation.getInternetConnectionProfile().getConnectionCost();<br />    <span style="color: rgb(0, 0, 255);">var</span> networkCostConstants = Windows.Networking.Connectivity.NetworkCostType;<br />    <span style="color: rgb(0, 0, 255);">var</span> Retval = <span style="color: rgb(0, 0, 255);">new</span> Object();<br />    <span style="color: rgb(0, 0, 255);">if</span> (connectionCost.roaming || connectionCost.overDataLimit)<br />    {<br />        Retval.Cost = CostGuidance.OptIn;<br />        Retval.CostName = <span style="color: rgb(0, 96, 128);">&quot;OptIn&quot;</span>;<br />        Retval.Reason = connectionCost.roaming<br />            ? <span style="color: rgb(0, 96, 128);">&quot;Connection is roaming; using the connection may result in additional charge.&quot;</span><br />            : <span style="color: rgb(0, 96, 128);">&quot;Connection has exceeded the usage cap limit.&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span> <span style="color: rgb(0, 0, 255);">if</span> (connectionCost.networkCostType == networkCostConstants.<span style="color: rgb(0, 0, 255);">fixed</span><br />        || connectionCost.networkCostType == networkCostConstants.variable)<br />    {<br />        Retval.Cost = CostGuidance.conservative;<br />        Retval.CostName = <span style="color: rgb(0, 96, 128);">&quot;Conservative&quot;</span>;<br />        Retval.Reason = connectionCost.networkCostType == NetworkCostType.<span style="color: rgb(0, 0, 255);">fixed</span><br />            ? <span style="color: rgb(0, 96, 128);">&quot;Connection has limited allowed usage.&quot;</span><br />            : <span style="color: rgb(0, 96, 128);">&quot;Connection is charged based on usage. &quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span><br />    {<br />        Retval.Cost = CostGuidance.Normal;<br />        Retval.CostName = <span style="color: rgb(0, 96, 128);">&quot;Normal&quot;</span>;<br />        Retval.Reason = connectionCost.networkCostType == networkCostConstants.unknown<br />            ? <span style="color: rgb(0, 96, 128);">&quot;Connection is unknown.&quot;</span><br />            : <span style="color: rgb(0, 96, 128);">&quot;Connection cost is unrestricted.&quot;</span>;<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> Retval;<br />}<br /></pre>
  </div>
</blockquote>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">enum</span> NetworkCost { Normal, Conservative, OptIn };<br /><span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">class</span> CostGuidance<br />{<br />    <span style="color: rgb(0, 0, 255);">public</span> CostGuidance()<br />    {<br />        var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();<br />        Init(connectionCost);<br />    }<br />    <span style="color: rgb(0, 0, 255);">public</span> NetworkCost Cost { get; <span style="color: rgb(0, 0, 255);">private</span> set; }<br />    <span style="color: rgb(0, 0, 255);">public</span> String Reason { get; <span style="color: rgb(0, 0, 255);">private</span> set; }<br /><br /><br />    <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">void</span> Init(ConnectionCost connectionCost)<br />    {<br />        <span style="color: rgb(0, 0, 255);">if</span> (connectionCost == <span style="color: rgb(0, 0, 255);">null</span>) <span style="color: rgb(0, 0, 255);">return</span>;<br />        <span style="color: rgb(0, 0, 255);">if</span> (connectionCost.Roaming || connectionCost.OverDataLimit)<br />        {<br />            Cost = NetworkCost.OptIn;<br />            Reason = connectionCost.Roaming<br />                ? <span style="color: rgb(0, 96, 128);">&quot;Connection is roaming; using the connection may result in additional charge.&quot;</span><br />                : <span style="color: rgb(0, 96, 128);">&quot;Connection has exceeded the usage cap limit.&quot;</span>;<br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span> <span style="color: rgb(0, 0, 255);">if</span> (connectionCost.NetworkCostType == NetworkCostType.Fixed<br />            || connectionCost.NetworkCostType == NetworkCostType.Variable)<br />        {<br />            Cost = NetworkCost.Conservative;<br />            Reason = connectionCost.NetworkCostType == NetworkCostType.Fixed<br />                ? <span style="color: rgb(0, 96, 128);">&quot;Connection has limited allowed usage.&quot;</span><br />                : <span style="color: rgb(0, 96, 128);">&quot;Connection is charged based on usage. &quot;</span>;<br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span><br />        {<br />            Cost = NetworkCost.Normal;<br />            Reason = connectionCost.NetworkCostType == NetworkCostType.Unknown<br />                ? <span style="color: rgb(0, 96, 128);">&quot;Connection is unknown.&quot;</span><br />                : <span style="color: rgb(0, 96, 128);">&quot;Connection cost is unrestricted.&quot;</span>;<br />        }<br />    }<br />}<br /></pre>

    <br /></div>
</blockquote>

<p>Utilisez l'<a href="http://code.msdn.microsoft.com/windowsapps/Network-Information-Sample-63aaa201" target="_blank">exemple d'informations réseau</a> pour en savoir plus sur l'adaptation du comportement de votre application aux connexions réseau limitées.</p>

<p>Les utilisateurs peuvent également exécuter le Gestionnaire des tâches pour connaître la consommation de données réseau de chaque application. La capture d'écran ci-dessous montre un exemple de ce comportement.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5618.task-manager_6C99F920.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5618.task_2D00_manager_5F00_6C99F920.png"><img title="L'onglet Historique des applications du Gestionnaire des tâches permet aux utilisateurs de connaître les quantités de ressources processeur et de ressources réseau consommées par les applications" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="L'onglet Historique des applications du Gestionnaire des tâches permet aux utilisateurs de connaître les quantités de ressources processeur et de ressources réseau consommées par les applications" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3554.task-manager_thumb_4C7EEC63.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3554.task_2D00_manager_5F00_thumb_5F00_4C7EEC63.png" width="600" height="545" /></a></p>

<p align="center"><em>L'onglet Historique des applications du Gestionnaire des tâches permet aux utilisateurs de connaître les quantités de ressources processeur et de ressources réseau consommées par les applications</em></p>

<h2>Réagir aux changements d'état du réseau</h2>

<p>Dans n'importe quel scénario impliquant un appareil mobile, les réseaux peuvent disparaître et réapparaître à tout moment. Un réseau haut débit mobile 3G ou 4G peut être hors portée dans la maison ou le garage de l'utilisateur, tandis que le Wi-Fi y sera plus facilement accessible. De même, le réseau Wi-Fi peut devenir hors portée lorsque l'utilisateur quitte son domicile. Il peut également arriver qu'aucun réseau ne soit disponible. Avec la prolifération des réseaux haut débit Wi-Fi et mobiles, les changements de réseau sont très fréquents. </p>

<p>Un événement <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a> indique que le <i>coût disponible</i> ou les <i>options de connectivité</i> ont peut-être changé. Pour réagir aux changements d'état du réseau et proposer à l'utilisateur une expérience client transparente dans cette situation, faites en sorte que vos applications connectées respectent les recommandations de ce scénario.</p>

<h3>Perte de connexion en raison d'une erreur</h3>

<p>Dans la plupart des cas, les connexions peuvent être rétablies en réessayant l'opération réseau. En cas d'échec, attendez un événement <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a>. Nous recommandons aux applications d'utiliser un intervalle d'interruption croissant entre les tentatives, en commençant par 50 millisecondes, puis en augmentant progressivement cet intervalle en cas d'échecs répétés.</p>

<h3>Perte de réseau</h3>

<p>Signalez à l'utilisateur que la connexion a été perdue, puis procédez à une inscription et attendez un événement <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a>.</p>

<h3>Nouvelle disponibilité réseau</h3>

<p>Dans certains cas, l'appareil est connecté à plusieurs réseaux. Par exemple, un utilisateur peut être connecté à un réseau mobile et converser en ligne avec des amis via l'application Messagerie de Windows 8, puis arriver à son domicile et se connecter au réseau illimité disponible. Par défaut, Windows 8 privilégie les réseaux illimités par rapport aux réseaux limités, ainsi que les réseaux plus rapides par rapport aux moins rapides. Cependant, les connexions existantes établies par une application ne basculent pas automatiquement sur un nouveau réseau. L'application doit être impliquée dans l'opération, car elle seule est capable de prendre la bonne décision quant au basculement ou non sur le nouveau réseau. </p>

<p>Par exemple, si un flux vidéo est presque terminé, il n'est peut-être pas judicieux de basculer sur le nouveau réseau. En revanche, si le réseau actuel perd des paquets ou est trop lent, ou si le transfert du flux risque de prendre encore beaucoup de temps, dans ce cas il est peut-être préférable de basculer sur le nouveau réseau.</p>

<p>Si vous déterminez qu'un changement de réseau est idéal dans les scénarios impliquant votre application, suivez ces recommandations lorsque vous détectez un nouveau réseau :</p>

<ol>
  <li>Vérifiez les coûts réseau du réseau existant et du nouveau réseau. S'il est judicieux de basculer sur le nouveau réseau, essayez d'établir une nouvelle connexion réseau et relancez l'opération réseau à partir des recommandations mentionnées ci-dessus. Windows sélectionne automatiquement le réseau illimité plutôt que le réseau à connexion limitée, et le réseau le plus rapide plutôt que le plus lent, le cas échéant.</li>

  <li>Si la connexion avec le nouveau réseau est établie, utilisez cette nouvelle connexion réseau dans votre application et annulez l'opération réseau initiale sur le réseau précédent, si la connexion existe encore.</li>
</ol>

<h3>Changement de coût réseau</h3>

<p>Un changement de coût réseau peut se produire lorsque la valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> est <b>Fixed</b> et que l'utilisation approche de la limite ou la dépasse. Un changement de coût réseau peut aussi se produire si la valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> devient <b>Variable</b> ou si la valeur de <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.connectioncost.roaming.aspx" target="_blank">Roaming</a> devient true. Dans ces cas, adaptez le comportement de l'application en fonction des recommandations énoncées pour le conseil précédent.</p>

<p>Ces exemples de code utilisent l'événement <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a> pour fournir une expérience utilisateur transparente au sein de l'application en cas de changements d'état du réseau de différente nature. Les deux exemples utilisent une variable booléenne globale appelée <i>registeredNetworkStatusNotification</i>, initialement définie sur <b>false</b>. </p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 128, 0);">// Register for NetworkStatusChanged notifications, and display new </span><br /><span style="color: rgb(0, 128, 0);">// Internet ConnectionProfile info upon network status change.</span><br /><span style="color: rgb(0, 0, 255);">function</span> registerForNetworkStatusChange() {<br />    <span style="color: rgb(0, 0, 255);">try</span> {<br /><br />        <span style="color: rgb(0, 128, 0);">// Register for network status change notifications.</span><br />        <span style="color: rgb(0, 0, 255);">if</span> (!registeredNetworkStatusNotification) {<br />            <span style="color: rgb(0, 0, 255);">var</span> networkInfo.addEventListener(<span style="color: rgb(0, 96, 128);">&quot;networkstatuschanged&quot;</span>, onNetworkStatusChange);<br />            registeredNetworkStatusNotification = <span style="color: rgb(0, 0, 255);">true</span>;<br />        }<br />    }<br />    <span style="color: rgb(0, 0, 255);">catch</span> (e) {<br />        print(<span style="color: rgb(0, 96, 128);">&quot;An unexpected exception occurred: &quot;</span> + e.name + <span style="color: rgb(0, 96, 128);">&quot;: &quot;</span> + e.message);<br />    }<br />}<br /><br /><span style="color: rgb(0, 128, 0);">// Event handler for NetworkStatusChanged event</span><br /><span style="color: rgb(0, 0, 255);">function</span> onNetworkStatusChange(sender) {<br />    <span style="color: rgb(0, 0, 255);">try</span> {<br />        <span style="color: rgb(0, 128, 0);">// Get the ConnectionProfile that is currently used to connect </span><br />        <span style="color: rgb(0, 128, 0);">// to the Internet.</span><br />        <span style="color: rgb(0, 0, 255);">var</span> internetProfile = networkInfo.getInternetConnectionProfile();<br />        <span style="color: rgb(0, 0, 255);">if</span> (internetProfile === <span style="color: rgb(0, 0, 255);">null</span>) {<br />            print(<span style="color: rgb(0, 96, 128);">&quot;Not connected to Internet\n\r&quot;</span>);<br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span> {<br />            internetProfileInfo += getConnectionProfileInfo(internetProfile) + <span style="color: rgb(0, 96, 128);">&quot;\n\r&quot;</span>;<br />            print(internetProfileInfo);<br />        }<br />        internetProfileInfo = <span style="color: rgb(0, 96, 128);">&quot;&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">catch</span> (e) {<br />        print(<span style="color: rgb(0, 96, 128);">&quot;An unexpected exception occurred: &quot;</span> + e.name + <span style="color: rgb(0, 96, 128);">&quot;: &quot;</span> + e.message);<br />    }<br />}<br /></pre>

    <br /></div>
</blockquote>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 128, 0);">// Register for NetworkStatusChanged notifications, and display new </span><br /><span style="color: rgb(0, 128, 0);">// Internet ConnectionProfile info upon network status change.</span><br /><span style="color: rgb(0, 0, 255);">void</span> NetworkStatusChange()<br />{<br />    <span style="color: rgb(0, 128, 0);">// Register for network status change notifications.</span><br />    <span style="color: rgb(0, 0, 255);">try</span><br />    {<br />        var networkStatusCallback = <span style="color: rgb(0, 0, 255);">new</span> NetworkStatusChangedEventHandler(OnNetworkStatusChange);<br />        <span style="color: rgb(0, 0, 255);">if</span> (!registeredNetworkStatusNotification)<br />        {<br />            NetworkInformation.NetworkStatusChanged += networkStatusCallback;<br />            registeredNetworkStatusNotification = <span style="color: rgb(0, 0, 255);">true</span>;<br />        }<br />    }<br />    <span style="color: rgb(0, 0, 255);">catch</span> (Exception ex)<br />    {<br />        rootPage.NotifyUser(<span style="color: rgb(0, 96, 128);">&quot;Unexpected exception occurred: &quot;</span> + ex.ToString(), NotifyType.ErrorMessage);<br />    }<br />}<br /><br /><span style="color: rgb(0, 128, 0);">// Event handler for NetworkStatusChanged event</span><br />async <span style="color: rgb(0, 0, 255);">void</span> OnNetworkStatusChange(<span style="color: rgb(0, 0, 255);">object</span> sender)<br />{<br />    <span style="color: rgb(0, 0, 255);">try</span><br />    {<br />        <span style="color: rgb(0, 128, 0);">// Get the ConnectionProfile that is currently used to connect </span><br />        <span style="color: rgb(0, 128, 0);">// to the Internet                </span><br />        ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();<br /><br />        <span style="color: rgb(0, 0, 255);">if</span> (InternetConnectionProfile == <span style="color: rgb(0, 0, 255);">null</span>)<br />        {<br />            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =&gt;<br />            {<br />                rootPage.NotifyUser(<span style="color: rgb(0, 96, 128);">&quot;Not connected to Internet\n&quot;</span>, NotifyType.StatusMessage);<br />            });<br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span><br />        {<br />            connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);<br />            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =&gt;<br />            {<br />                rootPage.NotifyUser(connectionProfileInfo, NotifyType.StatusMessage);<br />            });<br />        }<br />        internetProfileInfo = <span style="color: rgb(0, 96, 128);">&quot;&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">catch</span> (Exception ex)<br />    {<br />        rootPage.NotifyUser(<span style="color: rgb(0, 96, 128);">&quot;Unexpected exception occurred: &quot;</span> + ex.ToString(), NotifyType.ErrorMessage);<br />    }<br />}<br /></pre>
  </div>
</blockquote>

<p>Pour en savoir plus sur l'événement <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a>, voir <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/hh700376.aspx" target="_blank">Démarrage rapide : gestion des événements de connexion et des changements de disponibilité</a> et l'<a href="http://code.msdn.microsoft.com/windowsapps/Network-Information-Sample-63aaa201" target="_blank">exemple d'informations réseau</a>.</p>

<h2>Mettre le contenu en cache pour plus de fluidité</h2>

<p>La mise en cache des contenus sur le disque permet d'améliorer les performances et la fluidité de votre application. Par exemple, une application de lecture de flux RSS peut afficher immédiatement les flux qui ont été mis en cache sur le disque au cours d'une session précédente. Dès que les derniers flux sont disponibles, l'application met à jour son contenu. La mise en cache permet à l'utilisateur de disposer immédiatement du contenu, dès le lancement de l'application, pendant que celle-ci récupère les nouveaux contenus.</p>

<p>Windows 8 fournit la classe <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.storage.applicationdata.aspx" target="_blank">ApplicationData</a><b></b> dans l'espace de noms <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.storage.aspx" target="_blank">Windows.Storage</a><b></b>. Cette classe permet d'accéder au magasin de données de l'application. Ce magasin de données se compose de fichiers et de paramètres qui sont soit stockés en local sur l'appareil, soit transférés en itinérance sur plusieurs appareils, soit temporaires.</p>

<p>Les fichiers sont idéaux pour stocker de gros jeux de données, des bases de données volumineuses ou des données stockées dans un format de fichier courant. Les fichiers peuvent se trouver dans les dossiers Roaming, Local ou Temporary. Ces dossiers sont utilisés de façon différente :</p>

<ul>
  <li>Les fichiers du dossier Roaming sont synchronisés sur tous les ordinateurs et appareils auxquels les utilisateurs se connectent en utilisant des comptes connectés. L'itinérance des fichiers n'est pas instantanée : le système prend en considération plusieurs facteurs pour déterminer à quel moment envoyer les données. L'utilisation de données itinérantes doit rester en dessous du quota (accessible via la propriété <a href="http://msdn.microsoft.com/fr-fr/library/windows/apps/windows.storage.applicationdata.roamingstoragequota.aspx" target="_blank">RoamingStorageQuota</a><b></b>). En cas de dépassement du quota, l'itinérance est suspendue. Les fichiers ne peuvent pas être déplacés pendant qu'une application est toujours en train d'écrire des données dans ces derniers. Pensez donc à fermer les objets fichier de votre application lorsqu'ils ne sont plus nécessaires. </li>

  <li>Les fichiers du dossier Local ne sont pas synchronisés entre les différents ordinateurs et appareils. Ils restent stockés sur l'ordinateur ou l'appareil sur lequel ils ont été écrits initialement. </li>

  <li>Les fichiers du dossier Temporary peuvent être supprimés s'ils ne sont pas utilisés. Le système prend en compte des facteurs tels que la capacité disponible sur le disque et l'ancienneté du fichier pour déterminer si un fichier temporaire doit ou non être supprimé.</li>
</ul>

<p>Ces exemples de code mettent en cache du contenu sur le disque. La mise en cache de la réponse du serveur permet à votre application de présenter immédiatement le contenu à l'utilisateur après une fermeture et une réouverture. Pour plus de concision, ces exemples ne montrent pas comment écrire des paramètres dans le magasin de données de l'application, ni comment répondre aux événements d'itinérance. Ces détails sont en revanche abordés dans l'<a href="http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2" target="_blank">exemple de données d'application</a>.</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> roamingFolder = Windows.Storage.ApplicationData.current.roamingFolder;<br /><span style="color: rgb(0, 0, 255);">var</span> filename = <span style="color: rgb(0, 96, 128);">&quot;serverResponse.txt&quot;</span>;<br /><br /><span style="color: rgb(0, 0, 255);">function</span> cacheResponse(strResponse) {<br />    roamingFolder.createFileAsync(filename, Windows.Storage.CreationCollisionOption.replaceExisting)<br />        .done(<span style="color: rgb(0, 0, 255);">function</span> (file) {<br />            <span style="color: rgb(0, 0, 255);">return</span> Windows.Storage.FileIO.writeTextAsync(file, strResponse);<br />        });<br />}<br /><br /><span style="color: rgb(0, 0, 255);">function</span> getCachedResponse() {<br />    roamingFolder.getFileAsync(filename)<br />        .then(<span style="color: rgb(0, 0, 255);">function</span> (file) {<br />            <span style="color: rgb(0, 0, 255);">return</span> Windows.Storage.FileIO.readTextAsync(file);<br />        }).done(<span style="color: rgb(0, 0, 255);">function</span> (response) {<br />            print(response);<br />        }, <span style="color: rgb(0, 0, 255);">function</span> () {<br />            <span style="color: rgb(0, 128, 0);">// getFileAsync or readTextAsync failed. </span><br />            <span style="color: rgb(0, 128, 0);">// No cached response.</span><br />        });<br />}<br /></pre>

    <br /></div>
</blockquote>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">MainPage rootPage = MainPage.Current;<br />StorageFolder roamingFolder = <span style="color: rgb(0, 0, 255);">null</span>;<br /><span style="color: rgb(0, 0, 255);">const</span> <span style="color: rgb(0, 0, 255);">string</span> filename = <span style="color: rgb(0, 96, 128);">&quot;serverResponse.txt&quot;</span>;<br /><br />async <span style="color: rgb(0, 0, 255);">void</span> cacheResponse(<span style="color: rgb(0, 0, 255);">string</span> strResponse)<br />{<br />    StorageFile file = await roamingFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);<br />    await FileIO.WriteTextAsync(file, strResponse);<br />}<br /><br />async <span style="color: rgb(0, 0, 255);">void</span> getCachedResponse()<br />{<br />    <span style="color: rgb(0, 0, 255);">try</span><br />    {<br />        StorageFile file = await roamingFolder.GetFileAsync(filename);<br />        <span style="color: rgb(0, 0, 255);">string</span> response = await FileIO.ReadTextAsync(file);<br />    }<br />    <span style="color: rgb(0, 0, 255);">catch</span> (Exception)<br />    {<br />        <span style="color: rgb(0, 128, 0);">// getFileAsync or readTextAsync failed.</span><br />        <span style="color: rgb(0, 128, 0);">// No cached response.</span><br />    }<br />}<br /></pre>

    <br /></div>
</blockquote>

<p>Pour plus d'informations sur le magasin de données des applications, consultez le billet <a href="http://blogs.msdn.com/b/windowsappdev_fr/archive/2012/07/26/roaming-von-app-daten.aspx" target="_blank">Itinérance des données de vos applications</a> et essayez de mettre en œuvre l'<a href="http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2" target="_blank">exemple de données d'application</a>.</p>

<h2>Pour résumer</h2>

<p>Lors de la planification de vos applications du Windows Store, suivez les recommandations énoncées dans ce billet pour proposer à l'utilisateur une expérience connectée, parfaite et sans la moindre complication. En suivant ces conseils, vous simplifierez vos processus de développement, tout en maintenant la fluidité de vos applications et en améliorant leur potentiel de confiance pour l'utilisateur.</p>

<p>- Suhail Khalid, chef de projet II, Windows</p>

<p>Avec la participation de Steven Baker et Peter Smith</p>

<!-- Title: “Créer des applications Windows Store connectées” 
Tags: “applications du Windows Store, HttpClient, applications connectées, XMLHTTPRequest, IXHR2, XML HTTP Request 2, WinJS.xhr” -->
</div>]]></content:encoded>
    </item>
    <item>
      <title>Inscrivez-vous dès maintenant à la conférence //build/ 2013 !</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_fr/inscrivez-vous-ds-maintenant-la-confrence-build2013</link>
      <pubDate>Fri, 05 Apr 2013 10:31:58 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_fr/2013/04/05/inscrivez-vous-ds-maintenant-la-confrence-build2013/</guid>
      <description><![CDATA[La semaine dernière, Steve Guggenheimer a annoncé la tenue de //build/ 2013. La conférence aura lieu...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"><p>La semaine dernière, Steve Guggenheimer <a href="http://blogs.technet.com/b/microsoft_blog/archive/2013/03/26/announcing-build-2013.aspx" target="_blank">a annoncé</a> la tenue de //build/ 2013. La conférence aura lieu du 26 au 28 juin 2013 au Moscone Center à San Francisco. //build/ est l'endroit idéal pour en apprendre davantage sur le développement d'applications du Windows Store. La conférence comprendra des présentations, des démonstrations, des sessions d'informations, etc. Nous sommes nombreux au sein de l'équipe de développement à nous rendre à San Francisco pour animer ces démonstrations et répondre à vos questions. La conférence est le meilleur endroit qui existe pour découvrir les dernières évolutions du développement d'applications du Windows Store. </p>  <p>Les inscriptions ont débuté le mardi 2 avril. Accédez au site <a href="http://www.buildwindows.com" target="_blank">www.buildwindows.com</a> pour connaître tous les détails de la conférence et vous inscrire. </p>  <p>En espérant vous y rencontrer !</p> <!-- Title: “Inscrivez-vous dès maintenant à la conférence //build/ 2013 !” Tags: “build” --></div>]]></content:encoded>
    </item>
  </channel>
</rss>