MSDN Magazine > Accueil > Tous les numéros > 2008 > Octobre >  À la pointe : Réutilisation de code dans WPF et...
À la pointe
Réutilisation de code dans WPF et Silverlight 2.
Dino Esposito

Téléchargement de code disponible ici : MSDN Code Gallery (604 Ko)
Parcourez le code en ligne

Cet article est basé sur une version préliminaire de Silverlight 2. Toutes les informations contenues dans cet article sont susceptibles d’être modifiées.

Dans Silverlight 2, vous utilisez le langage XAML (Extensible Application Markup Language) pour concevoir et afficher l'interface utilisateur. En même temps, vous utilisez le CLR de base intégré pour traiter le code géré dans le navigateur. Par conséquent, il existe une forte similarité entre les applications Silverlight 2 basées sur le Web et les applications de bureau Windows Presentation Foundation. L'un des avantages que confère l'utilisation d'un même modèle de programmation est qu'il permet de réutiliser aisément le code entre les deux types d'applications. Dans cet article, j'aborderai quelques modèles qui permettent de faciliter au maximum le partage du code et du balisage XAML entre Silverlight 2 et WPF.

Compatibilité WPF et Silverlight 2
Avec l'introduction de Silverlight 2, le XAML s'apprête à devenir l'API d'une nouvelle génération de modules d'interface utilisateur. Silverlight 2 prend en charge un sous-ensemble de l'infrastructure WPF, notamment des fonctionnalités pour la gestion de mise en page riche, la liaison de données, les styles, les médias, l'animation, les graphiques et les modèles.
Cependant, la prise en charge complète de XAML dans Silverlight 2 est limitée par la taille du plug-in téléchargeable. En quelques mégaoctets seulement (moins de 5 Mo dans Bêta 2), le plug-in de Silverlight 2 doit fournir le CLR de base, une version de Microsoft .NET Framework 3.5 incluant WPF et un sous-ensemble de la plate-forme du client Windows Communication Foundation (WCF), un analyseur XAML et un certain nombre de contrôles spécifiques à Silverlight.
Dans Silverlight 2, les fonctionnalités graphiques 3D de WPF ne sont pas prises en charge, et certains attributs et éléments ont été soit écartés soit réduits. En fin de compte, cependant, vous disposez d'un sous-ensemble compatible qui vous permet de créer une version Silverlight d'une interface utilisateur WPF modérément complexe. Nous aborderons les domaines de compatibilité critiques dans un moment.
Notez, toutefois, que Microsoft ajoute également dans Silverlight de nouvelles API qui n'ont peut-être pas d'homologue dans la version de bureau de WPF. Les fonctionnalités les plus pertinentes incluent des contrôles tels que DataGrid et des classes telles que WebClient pour les appels réseau de type GET simples. Ces fonctionnalités seront également ajoutées à WPF.

Présentation de Visual State Manager
Une autre fonctionnalité qui est livrée avec Silverlight 2 et qui sera ajouté à WPF est le superbe gestionnaire VSM (Visual State Manager) pour les contrôles. VSM simplifie le développement de modèles de contrôles interactifs en introduisant des états visuels et des transitions d'état. Depuis l'introduction de WPF, les développeurs pouvaient personnaliser l'aspect et le comportement des contrôles WPF grâce aux modèles et styles. Par exemple, vous pouviez non seulement modifier la forme et l'apparence d'un contrôle mais aussi définir une nouvelle action ou animation correspondant au moment où un contrôle est activé, où il est en focus, où il perd le focus et ainsi de suite.
Avec VSM, les états visuels et transitions d'état font une partie de ce travail pour vous. Les états visuels VSM types sont normal, mouse-over (passage de la souris), disabled (désactivé) et focused (en focus). Pour chacun de ces états, vous pouvez définir un style ou une forme. Les transitions d'état définissent le passage du contrôle d'un état à l'autre. Vous définissez généralement les transitions avec des animations. Au moment de l'exécution, Silverlight lira l'animation appropriée et appliquera le style spécifié pour faire passer le contrôle d'un état à l'autre de façon élégante et fluide.
Pour définir un état visuel, insérez un fragment de balisage dans le modèle de contrôle, comme indiqué ici :
<vsm:VisualStateManager.VisualStateGroups>
  <vsm:VisualStateGroup x:Name="CommonStates">
    <vsm:VisualState x:Name="MouseOver">
      <Storyboard>
        ...
      </Storyboard>
    </vsm:VisualState>
  </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
Chaque contrôle définit un ou plusieurs groupes d'états tels que CommonStates et FocusStates. Chaque groupe, à son tour, définit des états visuels spécifiques tels que MouseOver, Pressed et Checked. Pour chaque état visuel et transition entre états, vous pouvez définir une table de montage que Silverlight lira automatiquement au moment opportun.
En résumé, il existe des fonctionnalités dans WPF que Silverlight 2 ne prend pas en charge et des fonctionnalités dans Silverlight 2 que WPF ne possède pas. Ces différences ont surtout un effet sur la compatibilité au niveau XAML. Pour une compatibilité complète, vous pouvez utiliser le sous-ensemble commun qui, fort heureusement, est suffisamment grand pour vous laisser faire pratiquement n'importe quoi.

Partage de code
Lorsque VSM sera disponible pour la version de bureau de WPF, vous pourrez utiliser la même approche pour Silverlight que pour les applications de bureau de Windows et partager les modèles de contrôles entre les projets WPF et Silverlight. D'ici là, voyons comment vous pouvez réutiliser le code entre les projets WPF de bureau et Web dès aujourd'hui.
Une application WPF est composé de code XAML et géré. Le code géré cible les classes de la version prise en charge de .NET. Il vous appartient d'utiliser un sous-ensemble commun de XAML que WPF de bureau et Silverlight 2 peuvent tous deux comprendre. Vous devez également organiser votre classe codebehind de sorte que les différences dans l'infrastructure principale soient traitées correctement.
En gros, il existe deux scénarios dans lesquels vous voudrez réutiliser le code WPF. Dans le premier, vous avez une application de bureau WPF existante et souhaitez la proposer sur le Web pour en simplifier la maintenance et le déploiement. Dans le second, vous voulez développer un frontal pour un système existant et le proposer à des clients Windows et Web.
J'examinerai la question de la réutilisation du code dans une perspective WPF vers Silverlight. Sur le plan des modèles de refactorisation de code et balisage, il existe très peu de différences.

Raisonnement concernant les applications WPF
Une application WPF type est créée à partir d'une arborescence d'objets dont la racine est Window. À son tour, l'élément Window contient plusieurs éléments enfants disposés ou empilés de plusieurs façons. Les éléments correspondent aux formes de base, aux gestionnaires de disposition, aux tables de montage séquentiel et aux contrôles (y compris les contrôles tiers et utilisateur personnalisés). Voici un exemple simple :
<Window x:Class="Samples.MyTestWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test App" Height="300" Width="350">
    <StackPanel Margin="10">
        ...
    </StackPanel>
</Window>
Ce code ne peut pas être intégré tel quel à une application Silverlight 2. Tout d'abord, l'élément Window n'est pas pris en charge dans Silverlight. Dans les assemblys Silverlight, une telle classe n'existe pas dans l'espace de noms System.Windows. La balise racine de toute application Silverlight est UserControl. L'élément est mappé sur la classe UserControl définie dans l'espace de noms System.Windows.
Voici l'en-tête modifié d'une application Silverlight :
<UserControl x:Class="Samples.MyTestWindow"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test App" Height="300" Width="350">
    <StackPanel Margin="10">
        ...
    </StackPanel>
</UserControl>
Tout le code de balisage que vous avez dans les limites des éléments <Window> et <UserControl> doivent continuer à correspondre. Il vous appartient de modifier le XAML de bureau original de sorte qu'il réponde aux exigences de l'analyseur XAML de Silverlight. Cette tâche bénéficie considérablement du haut niveau de compatibilité entre les deux syntaxes. Dans la plupart des cas, l'ajustement du XAML se résume à l'ajustement de quelques éléments et attributs. Voyons deux exemples.
Le WPF de bureau comporte un élément <label> que Silverlight ne reconnaît pas. Lorsque vous transférez cette balise dans Silverlight, vous devez trouver une solution de contournement pour l'étiquette. Un rectangle contenant un bloc de texte pourrait faire l'affaire.
Dans WPF, vous pouvez associer une info-bulle à des contrôles à l'aide de l'attribut ToolTip, comme suit :
<Button Tooltip="Click me" ... />
Dans Silverlight 2, l'attribut ToolTip n'est pas pris en charge. Vous devez recourir à ToolTipService, comme dans les extraits de code suivants :
<Button ToolTipService.ToolTip="Click me" ... />
Notez que les deux solutions fonctionnent dans le WPF de bureau. Par ailleurs, ToolTipService propose plusieurs propriétés d'info-bulle supplémentaires dans le WPF de bureau telles que le placement, le décalage, le retard initial et la durée. Cependant, aucune de ces propriétés supplémentaires n'est prise en charge par Silverlight.
Existe-t-il d'autres problèmes de compatibilité entre WPF et Silverlight ? Cela dépend de la manière dont vous utilisez WPF. En général, le portage d'une application WPF importante vers Silverlight est difficile et n'est en fait même pas un objectif principal. Pour commencer, dans Silverlight 2, vous n'avez pas de déclencheurs éparpillés un peu partout, là où vous en avez besoin. Par exemple, il y a une collection Triggers sur les éléments d'interface utilisateur, des descendants de FrameworkElement, mais pas dans les styles, les données et les modèles de contrôles.
De même, la liaison de données est prise en charge dans Silverlight mais pas de la même manière que dans WPF. Par exemple, vous avez l'élément Binding, le contexte de données, les modèles de données et les collections observables. Comme je l'ai déjà mentionné, vous n'avez pas de déclencheur et une balise XAML simplifiée vous oblige à écrire du code plus souvent que dans WPF. De plus, l'implémentation interne est tout à fait différente. L'objet Binding de Silverlight possède beaucoup moins de propriétés que dans WPF.
La globalisation est un autre aspect qui vous peut vous causer des problèmes. Pour des raisons de performances, le CLR de base n'inclut pas ses propres données de globalisation pour toutes les cultures prises en charge. Au lieu de cela, la classe CultureInfo de Silverlight s'appuie sur la fonctionnalité de globalisation fournie par le système d'exploitation sous-jacent. Cela signifie qu'il n'y a pas moyen de donner les mêmes paramètres de globalisation aux applications sur différents systèmes d'exploitation.
Enfin, WPF possède un jeu plus riche de contrôles qui ne sont pas disponibles dans Silverlight. Le contrôle RichTextBox en est un bon exemple.
En résumé, le portage d'une application Silverlight vers WPF est relativement simple, bien qu'en tant que développeur, vous deviez vous soucier des problèmes de performances qui risquent d'être causés par le modèle objet plus riche. L'important est de vous rappeler que Silverlight prend en charge un sous-ensemble des possibilités offertes par le WPF de bureau ; à vous de concevoir une solution interplates-formes en choisissant les fonctionnalités appropriées.

Écriture de code WPF interplate-forme
Le meilleur moyen de transférer du code des projets WPF aux projets Silverlight est d'utiliser les contrôles utilisateur. Outre un espace de noms XML distinct et des différences de balisage, un contrôle utilisateur est le seul moyen de partager le balisage et le code entre le WPF de bureau et Web.
Si votre application WPF est organisée de façon native ou si elle peut être refactorisée de sorte à utiliser largement les contrôles utilisateur, le portage de code vers Silverlight sera beaucoup plus facile que l'autre option, beaucoup moins attrayante, qui consiste à couper et coller.
Les assemblys peuvent-ils donc être partagés entre les projets WPF et Silverlight ? Dans Silverlight 2, vous pouvez certainement créer des bibliothèques de classes personnalisées, intégrées à des assemblys. Toutefois, n'oubliez pas que ces bibliothèques ciblent la version Silverlight de .NET Framework et utilisent un modèle de sécurité différent (pour en savoir plus à ce sujet, consultez la chronique Les coulisses du CLR de ce mois).
Les assemblys que vous utilisez dans une application WPF de bureau doivent tous être recompilés en tant que bibliothèques de classes Silverlight pour garantir qu'ils font référence aux bons assemblys et qu'ils effectuent des appels valides aux classes. Inutile de dire que ce processus de recompilation peut créer du travail supplémentaire pour réparer les appels aux classes non supportées.
En résumé, avec un peu de travail, vous pouvez prendre une application WPF et l'exposer sur le Web par le biais de Silverlight. Ce faisant, vous exposez votre code sur plusieurs plates-formes autres que Windows sans obliger les clients à disposer du .NET Framework complet. La figure 1 présente une application de bureau autonome WPF simple. La figure 2 présente la même application hébergée dans Internet Explorer par Silverlight.
Figure 1 Exemple d'application WPF
Figure 2 Application WPF adaptée pour Silverlight (Cliquez sur l'image pour l'agrandir)

Analyse du code géré
Pour une raison quelconque, la réutilisation du code entre WPF et Silverlight est perçue comme un problème lié à XAML. Comme je l'ai déjà mentionné, vous êtes confronté à des problèmes de XAML lorsque vous adaptez votre code, mais le plus gros problème se situe au niveau de la classe codebehind.
Dans Windows et Silverlight, un fichier XAML est associé à une classe code­behind écrite dans C# ou dans un autre langage géré. Malheureusement, ces classes codebehind ciblent différentes versions de .NET Framework. La version de bureau de WPF s'appuie sur la bibliothèque de classes de base (BCL) complète de .NET Framework 3.5, tandis que Silverlight 2 utilise une version légère de la bibliothèque BCL.
La version Silverlight de la BCL est beaucoup plus petite, mais elle prend quand même en charge les fonctionnalités de base telles que les collections, la réflexion, les expressions régulières, la manipulation de chaînes, le threading et les minuteurs. Vous disposez également d'outils qui vous permettent d'appeler divers services tels que les services Web XML, les services WCF et ADO.NET Data Services. Par ailleurs, vous disposez d'une riche prise en charge réseau pour communiquer sur HTTP, avec les services POX (Plain Old XML) et REST (Representational State Transfer), et, en général, atteindre n'importe quel point de terminaison HTTP public. La prise en charge réseau inclut également les sockets (inter domaines) et la communication en duplex.
Enfin, la BCL Silverlight offre une bonne prise en charge du traitement des données XML, y compris les versions ad hoc des classes XmlReader et XmlWriter. Ces classes sont pratiquement identiques aux classes analogues de la version de bureau de .NET Framework.
S'appuyant sur ces fonctionnalités de base, Silverlight 2 offre également une prise en charge complète LINQ to Objects, LINQ to XML et des arborescences d'expression. À partir de Bêta 2, Microsoft a également ajouté un tout nouveau fournisseur JSON (JavaScript Object Notation) pour exécuter les requêtes LINQ directement sur les données JSON.
Notons, par ailleurs, que la mise en réseau dans Silverlight ne peut se faire que de manière asynchrone. Pour effectuer un appel synchrone, vous devez recourir à un stratagème qui consiste essentiellement à invoquer la couche d'interopérabilité du navigateur et à atteindre l'implémentation par le navigateur de XMLHttpRequest, chaque fois que cela est possible (pour plus d'informations à ce sujet, consultez l'article à l'adresse go.microsoft.com/fwlink/?LinkId=124048).
Le point important, c'est que les classes codebehind de WPF et Silverlight s'appuient sur des bibliothèques de classes très différentes. Bien plus que toute différence au niveau du XAML, c'est ce fait qui constitue un obstacle à la réutilisabilité. Examinons donc ce problème.

Élaboration d'une stratégie pour le code critique
Lorsque vous écrivez du code qui doit être partagé par les services d'exécution Silverlight et Windows, vous devez savoir exactement ce que chaque plate-forme prend en charge. Dans l'idéal, vous aurez une liste de tâches demandées qui nécessitent un traitement spécial sur chaque plate-forme. Ensuite, vous devrez isoler ces éléments de code dans un objet et en extraire une interface.
Vous disposerez alors d'un bloc de code entièrement réutilisable qui obtient des fonctionnalités critiques en appelant des composants séparés. Le portage d'une telle une application vers Silverlight (ou WPF) consisterait alors simplement à remplacer des composants critiques par d'autres composants spécifiques à la plate-forme. Étant donné que tous ces composants exposent toujours une interface commune, leur implémentation est transparente au bloc de code principal.
Le modèle qui sous-tend cette approche est le modèle « Strategy » (Stratégie). Pour une définition formelle de ce modèle, voir go.microsoft.com/fwlink/?LinkId=124047. En gros, le modèle Strategy (Stratégie) est utile à chaque fois que vous devez modifier dynamiquement l'algorithme utilisé pour effectuer une certaine tâche dans une application.
Une fois que vous avez identifié une région de votre code pouvant potentiellement varier en fonction des conditions d'exécution, vous définissez une interface qui spécifie le comportement abstrait de votre code. Ensuite, vous créez une ou plusieurs classes Strategy qui implémentent l'interface et représentent ainsi différentes façon d'accomplir le comportement abstrait. En modifiant alors la classe Strategy, vous modifiez tout simplement votre manière de résoudre l'algorithme défini par l'interface. Ce faisant, vous dissociez l'implémentation même du comportement (la stratégie) du code qui l'utilise.
Dans ASP.NET, par exemple, le modèle Strategy (Stratégie) est utilisé dans l'implémentation du modèle de fournisseur pour l'appartenance, les rôles, les profils utilisateur, etc. Le service d'exécution ASP.NET sait qu'il existe une interface particulière pour les appartenances et les utilisateurs, par exemple. Il sait également comment trouver et instancier les classes concrètes pour ces types d'interface. Toutefois, les composants d'exécution dépendent uniquement de l'interface, ce qui rend les détails de la classe concrète inutiles pour ASP.NET.

Examen d'un exemple
Considérons l'exemple d'application illustré par les figures 1 et 2. Dans Silverlight et Windows, l'application présente un formulaire dans lequel les utilisateurs peuvent taper un symbole boursier pour obtenir une cotation. La figure 3 illustre le diagramme de l'application lorsque l'utilisateur clique sur le bouton. L'interface utilisateur se sert d'un modèle MVP (Model-View-Presenter) pour transmettre, dans une seule classe Presenter (présentateur), toute la logique derrière l'interface utilisateur. Le présentateur, à son tour, invoque une classe QuoteService interne qui répond en envoyant un objet StockInfo renfermant toutes les informations qui doivent être intégrées à l'interface utilisateur (voir la figure 4).
Figure 3 Diagramme du comportement de l'application (Cliquez sur l'image pour l'agrandir)
namespace Samples
{
    class SymbolFinderPresenter
    {
        // Internal reference to the view to update
        private ISymbolFinderView _view;

        public SymbolFinderPresenter(ISymbolFinderView view) {
            this._view = view;
        }

        public void Initialize() { }

        // Triggered by the user's clicking on button Find
        public void FindSymbol() {
            // Clear the view before operations start
            ClearView();

            // Get the symbol to retrieve 
            string symbol = this._view.SymbolName;
            if (String.IsNullOrEmpty(symbol)) {
                _view.QuickInfoErrorMessage = "Symbol not found.";
                return;
            }

            QuoteService service = new QuoteService();
            StockInfo stock = service.GetQuote(symbol);

            // Update the view
            UpdateView(stock);
        }

         private void ClearView() {
            _view.SymbolDisplayName = String.Empty;
            _view.SymbolValue = String.Empty;
            _view.SymbolChange = String.Empty;
            _view.ServiceProviderName = String.Empty;
        }

        private void UpdateView(StockInfo stock) {
             // Update the view
            _view.QuickInfoErrorMessage = String.Empty;
            _view.SymbolDisplayName = stock.Symbol;
            _view.SymbolValue = stock.Quote;
            _view.SymbolChange = stock.Change;
            _view.ServiceProviderName = stock.ProviderName;
        }
     }
}
La classe QuoteService ne tente pas de récupérer des cotations elle-même. Elle crée tout d'abord un composant fournisseur puis s'y soumet. La classe QuoteService implémente un algorithme très simple. Si une connexion Internet existe, elle utilise une classe de fournisseur utilisant un service Web public pour obtenir des données financières ; sinon, elle passe à un faux fournisseur qui ne renvoie que des nombres aléatoires. À un moment donné, donc, la classe QuoteService a besoin de vérifier s'il existe une connexion Internet, comme illustré à la figure 5.
public StockInfo GetQuote(string symbol)
{
    // Get the provider of the service
    IQuoteServiceProvider provider = ResolveProvider();
    return provider.GetQuote(symbol);
}
private IQuoteServiceProvider ResolveProvider()
{
    bool isOnline = IsConnectedToInternet();
    if (isOnline)
        return new FinanceInfoProvider();

    return new RandomProvider();
}
Jusqu'ici, il n'existe aucune différence entre Silverlight et WPF, et tout le code est entièrement réutilisable. Pour vérifier la présence d'une connexion Internet dans .NET, vous pouvez utiliser certaines des méthodes statiques de l'objet NetworkInterface. Cet objet est défini dans l'espace de noms System.Net.NetworkInformation. La méthode GetIsNetworkAvailable, en particulier, renvoie une valeur booléenne qui indique si une connexion réseau quelconque est disponible. Malheureusement, ceci ne nous dit pas grand-chose sur la connectivité Internet. Pour vous assurer que vous avez également accès à Internet, la seule méthode fiable consiste à d'essayer d'exécuter une commande ping sur un hôte (voir la figure 6).
private bool IsConnectedToInternet()
{
    string host = "...";
    bool result = false;
    Ping p = new Ping();
    try
    {
        PingReply reply = p.Send(host, 3000);
        if (reply.Status == IPStatus.Success)
            return true;
    }
    catch { }

    return result;
}
Le seul problème avec la figure 6, c'est que le code n'est pas pris en charge dans Silverlight 2. (Il n'est de même pas pris en charge par l'objet NetworkInterface). Vous devez isoler ce code (et tout autre code qui risque de créer des problèmes de compatibilité) dans une classe remplaçable. (Pour plus d'informations sur cette restriction, consultez l'encadré CoreCLR dans Silverlight qui accompagne cet article). Dans le code source associé, je crée une interface d'utilitaire pour ces types de méthodes potentiellement problématiques et crée ensuite des classes Strategy qui implémentent l'interface pour chaque plate-forme, comme illustré à la figure 7.
public partial class SilverCompatLayer : ICompatLib
{
    public bool IsConnectedToInternet()
    {
        string host = "...";
        bool result = false;
        Ping p = new Ping();
        try
        {
            PingReply reply = p.Send(host, 3000);
            if (reply.Status == IPStatus.Success)
                return true;
        }
        catch { }

        return result;
    }

    public string GetRawQuoteInfo(string symbol)
    {
        string output = String.Empty;
        StreamReader reader = null;

        // Set the URL to invoke
        string url = String.Format(UrlBase, symbol);

        // Connect and get response
        WebRequest request = WebRequest.Create(url);
        WebResponse response = request.GetResponse();

        // Read the response
        using (reader = new StreamReader(response.GetResponseStream()))
        {
           output = reader.ReadToEnd();
           reader.Close();
        }

        return output;
    }

    // A few other methods that require a different implementation 
    // (See source code)
    ...
}
Ici, l'interface dissocie la classe Strategy spécifique à la plate-forme de l'application hôte. En dissimulant alors le code qui instancie la classe Strategy concrète derrière une méthode de fabrique, il est possible d'utiliser le code suivant en toute sécurité dans WPF et Silverlight :
private bool IsConnectedToInternet()
{
    ICompatLib layer = ServiceResolver.ResolveCompatLayer();
    return layer.IsConnectedToInternet();
}
La classe SilverCompatLayer réside dans un assembly séparé. Cet assembly est le seul élément que vous devez changer lors du portage de votre code de WPF vers Silverlight ou inversement.
Après avoir créé les classes Strategy spécifiques à une plate-forme, il ne vous reste plus qu'à créer une version Silverlight de l'application. Le projet Silverlight qui est dérivé de l'application WPF originale contient des copies exactes de tous les fichiers à l'exception de l'assembly Compatibility.
Vous remarquerez dans le téléchargement de code associé à cet article que j'ai déterminé l'implémentation de stratégie à utiliser en instanciant la classe concrète explicitement dans une méthode de fabrique. Vous pouvez instancier des classes directement avec cette méthode ou lire leurs noms depuis un fichier de configuration et utiliser la réflexion pour obtenir des instances. Ces détails d'implémentation dépendent surtout du type de système que vous créez. Concernant la compatibilité WPF vers Silverlight, les stratégies et la superposition sont des concepts clés à maîtriser.

Considérations finales
Dans l'exemple d'application, j'effectue un appel réseau. Dans l'application WPF originale, l'appel est synchrone. Dans Silverlight 2, toutefois, les appels réseau synchrones ne sont pas du tout pris en charge. Le seul moyen d'effectuer des appels synchrones est d'utiliser l'astuce mentionnée précédemment qui consiste à appeler l'implémentation par le navigateur de XMLHttpRequest. (Pour plus d'informations, voir le code source).
Dans l'exemple de code, j'ai réussi à transférer mon application WPF originale sur le Web. Lors du portage de votre code, vous pourriez également considérer les fonctionnalités natives de l'environnement Silverlight et modifier la structure de votre application lorsque vous l'ajustez. Notez que dans mon exemple simple, la réécriture de l'application à l'aide du modèle de programmation de Silverlight aurait nécessité moins de code et moins d'effort que son adaptation depuis une application WPF.
WPF et Silverlight ont donc beaucoup de points communs pour tout ce qui est purement visuel, comme par exemple XAML. Toutefois, le modèle de programmation sous-jacent est un peu différent, et les solutions qui fonctionnent dans WPF ne peuvent pas toujours être appliquées telles quelles à Silverlight et inversement. Ceci dit, le partage de XAML et de code entre les applications WPF et Silverlight est tout à fait possible.

Veuillez envoyer vos questions et commentaires à l'attention de Dino à l'adresse cutting@microsoft.com.

Dino Esposito est actuellement architecte à IDesign et est l'auteur de Programming ASP.NET 3.5 Core References. Basé en Italie, Dino participe régulièrement aux différentes manifestations du secteur organisées aux quatre coins du monde. Vous trouverez son blog à l'adresse : weblogs.asp.net/despos.

Page view tracker