Pour ceux qui se demandent comment marche Silverlight et par quel bout prendre la chose, cet article est fait pour vous. Dans cet article on va analyser la coquille vide créée par Visual Studio pour bien comprendre les mécanismes mis en évidence dans le projet exemple.
Nous allons commencer par créer un projet de type « Silverlight navigation application » (Si vous avez besoin d’aide, reportez vous à ce post)
Concentrons nous maintenant sur la solution générée, qui doit avoir cette allure :
Nous avons donc 2 projets :
- NavigationApp.web : application web qui va contenir notre application Silverlight.
- NavigationApp : notre application silverlight
NavigationApp.web
Le projet est une application web, nous remarquons les deux pages de tests suivantes : NavigationAppTestPage.aspx NavigationAppTestPage.html. Ces deux pages mettent en œuvre l’hébergement de l’application Silverlight NavigationApp.xap en se basant sur le fichier Silverlight.js. Si on ouvre la page html (ou aspx) on va trouver essentiellement la balise Object qui va nous permettre d’inclure notre application Silverlight dans la page.
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/NavigationApp.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40818.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>
Dans la balise object, nous pouvons définir plusieurs paramètres dont :
- Source : qui est le binaire à télécharger.
- onError : la fonction javascript à executer lorsqu’une exception non catchée est levée au sein de l’application Silverlight.
- backgroung : la couleur de fond de l’application silverlight.
- minRuntimeVersion : La version minimale du plugin silverlight pouvant exécuter le binaire.
- autoUpgrade : Définit une valeur qui indique si une version du plug-in Silverlight antérieure au minRuntimeVersion spécifié tente de se mettre à jour automatiquement.
La liste complète des paramètres que nous pouvons définir pour une balise object est ici, ce qu’il faut retenir c’est que dès que nous voulons changer quelque chose par rapport à l’intégration de l’application ou du plugin silverlight au sein de la page c’est de ce côté ci qu’il faut regarder :)
L’iframe « _sl_historyFrame » est utilisée pour gérer l’histoique de navigation au sein de l’application Silverlight. Elle est partagée par toutes les applications Silverlight dans une même page.
Vous avez certainement remarqué que le fichier Silverlight.js est inclus dans ces pages de test. Ce fichier permet principalement de faire 2 types de fonctionnalités :
- Inclure programmatiquement une application Silverlight.
- Améliorer la procédure d'installation ou de mise à niveau standard de Silverlight.
Vous trouverez ici la liste des fonctions que propose ce fichier js.
Je pense qu’on a fait le tour de l’application web, tournons nous maintenant vers l’application Silverlight.
NavigationApp
C’est le projet qui contient notre application silverlight. Le point d’entrée de cette application est le fichier App.xaml, donc commençons déjà par analyser ce fichier. Son contenu devrait ressembler à ça :
<Application
x:Class="NavigationApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
On voit tout de suite que c’est une application avec la balise <Application>. Dans ce fichier on va définir toutes les ressources au niveau de l’application, ici à titre d’exemple, la ressource est un fichier xaml contenant tous les styles de l’application.
Dans le code behind de l’App.xaml on s’abonne aux évènements « Startup » et « UnhandledException » en définissant le comportement de l’application lorsque ces deux évènements sont déclanchés.
Lors du démarrage de l’application, l’évènement « Startup » est déclanché, si on regarde le comportement de l’application au Startup nous allons trouver la ligne de code suivante :
this.RootVisual = new MainPage();
A l’aide de cette ligne nous allons instancier notre conteneur d’écrans (pages) qui est ici MainPage.
Allons du coup du côté de MainPage.xaml : La première chose que nous allons remarquer c’est que MainPage est un UserControl, on le voit à l’aide de la balise <UserControl> au tout début du fichier xaml. Mais au fait, comment est chargé le xaml ? parce que ce qu’on a vu c’est qu’on fait un new MainPage(). Si nous regardons le constructeur dans le code behind de Mainpage.xaml nous allons nous apercevoir qu’il y a une méthode qui s’appelle InitializeComponents
En effet, dans le « Solution Explorer », positionnez vous au niveau du projet et cliquer sur l’icône « Show all files » comme suit :
Vous allez voir apparaître les répertoires cachés bin et obj. Dans le répertoire obj -> Debug ouvrez le fichier qui s’appelle MainPage.g.cs. Vous allez y trouver la méthode InitializeComponents que nous cherchions. Dans cette méthode nous allons charger le xaml et tous ces contrôles. Vous trouverez un fichier .g.cs pour chaque xaml que vous créez dans votre projet.
Retournons à notre xaml MainPage maintenant, nous avons dit qu’il contient une balise <UserControl> qui disait que MainPage était un UserControl, cette balise contient quelques attributs lui pêrmettant de charger les espaces de noms de librairies comme Navigation ou Control … Ensuite on trouve 2 grandes parties :
1 - Navigation frame
<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"
Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed">
<navigation:Frame.UriMapper>
<uriMapper:UriMapper>
<uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
</uriMapper:UriMapper>
</navigation:Frame.UriMapper>
</navigation:Frame>
Navigation frame va acceuillir une navigation page qui sera définie par la logique d’uri mapping. En fait notre UserControl MainPage joue le rôle de conteneur comme une MasterPage en ASP.NET : nous allons mettre dedans l’allure générale que doivent avoir nos pages et nous allons définir les zones (Navigation frame) dans les quelles nous allons acceuillir des navigation pages.
L’uri mapping, permet de faire le mapping entre l’url demandée et la page délivrée au client. Regardons tout d’abord la balise <navigation:Frame> qui est caractérisée par les attributs suivants :
- x:Name : le nom du contrôle
- Style : son style (Styles.xaml)
- Source : l’Uri par défaut
- Navigated : définit ce que doit faire l’application après qu’on ai navigué vers une page
- NavigationFailed : définit ce que doit faire l’application lorsque la navigation vers une page échoue
Ici nous définissons quelques règles de mapping d’uri en disant que si la page demandée est vide (Uri= «») donc l’url demandée ressemble à celle-ci : http://mondomaine/NavigationAppTestPage.aspx la navigation frame va alors contenir la page par défaut qui est /Views/Home.xaml. Et si la page demandée est /{PageName} la navigation frame va alors contenir la page /Views/{PageName}.xaml. Essayons maintenant d’analyser notre situation de départ en démarrant le projet, nous allons lancer la page NavigationAppTestPage.aspx et le navigation frame va demander l’Uri « /Home » définie dans l’attribut « Source » de la balise « navigation :Frame ». l’Uri /Home va donc être mappée à /Views/Home.xaml grâce à cette règle :
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
et la navigation frame va donc contenir la page Home.xaml.
2- Banière
<Grid x:Name="NavigationGrid" Style="{StaticResource NavigationGridStyle}">
<Border x:Name="BrandingBorder" Style="{StaticResource BrandingBorderStyle}">
<StackPanel x:Name="BrandingStackPanel" Style="{StaticResource BrandingStackPanelStyle}">
<ContentControl Style="{StaticResource LogoIcon}"/>
<TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}"
Text="Application Name"/>
</StackPanel>
</Border>
<Border x:Name="LinksBorder" Style="{StaticResource LinksBorderStyle}">
<StackPanel x:Name="LinksStackPanel" Style="{StaticResource LinksStackPanelStyle}">
<HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}"
NavigateUri="/Home" TargetName="ContentFrame" Content="home"/>
<Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>
<HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}"
NavigateUri="/About" TargetName="ContentFrame" Content="about"/>
</StackPanel>
</Border>
</Grid>
Ce code permet de dessiner la banière qu’il y a en haut avec le logo, le nom de l’application et les boutons, nous n’allons pas nous attarder sur cette partie parce que c’est uniquement l’utilisation de composants graphique.
Le répertoire /Views
Concentrons nous tout d’abord sur Home.xaml et About.xaml. Ces deux fichiers sont de type navigation page. Les navigation pages est un apport de la version 3 de Silverlight. En fait, Silverlight 3 embarque un framework de navigation et du coup nous pouvons désormais naviguer entre les pages xaml d’une application Silverlight en utilisant le navigateur.
Il ne nous reste plus qu’à jeter un coup d’œil sur la page ErrorWindow.xaml qui est dans le répertoire Views. Cette page est de type childWindow, dans la terminologie web c’est une popup.
Résumé
Voila voila, l’analyse du projet exemple est finie, nous avons vu :
- Que App.xaml est le point d’entrée de l’application Silverlight.
- Que dans App.xaml nous pouvons définir les ressources de l’application.
- Dans App.xaml.cs, nous définissons notre UserControl conteneur en faisant this.RootVisual= new MainPage() dans le code behind de App.xaml.
- Dans MainPage.xaml nous définissons l’ossature de l’application (un peu comme une Master Page) et les zones (Navigation Frame) qui peuvent acceuillir du contenu(Navigation Pages).
- Que dans une Navigation frame nous pouvons définir l’uri mapping.
- Les pages Home et About sont de type Navigation Page et sont hébergés par une navigation frame.
- Silverlight 3 embarque un framework de navigation permettant de naviguer entre les pages d’une application silverlight.
- Une ChildWindow est l’équivalent d’une popup dans le monde web.
Il reste néanmoins énormément de choses à voir comme les composants graphiques, comment accéder aux données serveur (puisqu’on est côté client), Les dependency proporty et attached property, DataBinding, … nous allons essayer de couvrir tous ces points dans de prochains posts.