Toute reprsentation ou reproduction, intgrale ou partielle, faite sans le consentement de MICRO APPLICATION est illicite (article L122-4 du code de la proprit intellectuelle). Avertissement aux utilisateurs Cette reprsentation ou reproduction illicite, par quelque procd que ce soit, constituerait une contrefaon sanctionne par les articles L335-2 et suivants du code de la proprit intellectuelle. Le code de la proprit intellectuelle nautorise, aux termes de larticle L122-5, que les reproductions strictement destines lusage priv et non destines lutilisation collective dune part, et dautre part, que les analyses et courtes citations dans un but dexemple et dillustration. Les informations contenues dans cet ouvrage sont donnes titre indicatif et nont aucun caractre exhaustif voire certain. A titre dexemple non limitatif, cet ouvrage peut vous proposer une ou plusieurs adresses de sites Web qui ne seront plus dactualit ou dont le contenu aura chang au moment o vous en prendrez connaissance. Aussi, ces informations ne sauraient engager la responsabilit de lEditeur. La socit MICRO APPLICATION ne pourra tre tenue pour responsable de toute omission, erreur ou lacune qui aurait pu se glisser dans cet ouvrage ainsi que des consquences, quelles quelles soient, qui rsulteraient des informations et indications fournies ainsi que de leur utilisation. Tous les produits cits dans cet ouvrage sont protgs, et les marques dposes par leurs titulaires de droits respectifs. Cet ouvrage nest ni dit, ni produit par le(s) propritaire(s) de(s) programme(s) sur le(s)quel(s) il porte et les marques ne sont utilises qu seule n de dsignation des produits en tant que noms de ces derniers. ISBN : 978-2-300-014314 Couverture ralise par Sbastien Wiegant MICRO APPLICATION 20-22, rue des Petits-Htels 75010 PARIS Tl. : 01 53 34 20 20 Fax : 01 53 34 20 00 Support technique : galement disponible sur www.microapp.com http://www.microapp.com
Retrouvez des informations sur cet ouvrage ! Rendez-vous sur le site Internet de Micro Application www.microapp.com. Dans le module de recherche, sur la page daccueil du site, entrez la rfrence 4 chiffres indique sur le prsent livre. Vous accdez directement sa che produit.
1431
Avant-propos
La collection Webmasters sadresse aux personnes inities au dveloppement de sites web qui souhaitent dcouvrir et mettre en pratique les nouvelles technologies Internet. Sans ngliger les aspects thoriques, nous donnons toujours priorit la pratique an que vous puissiez rapidement tre autonome. travers les diffrents titres de cette collection vous dcouvrirez les technologies qui font le web 2.0 et feront ce que certains nomment dj le web 3.0.
Conventions typographiques
An de faciliter la comprhension des techniques dcrites, nous avons adopt les conventions typographiques suivantes :
j j j j
gras : menu, commande, bote de dialogue, bouton, onglet. italique : zone de texte, liste droulante, case cocher, bouton radio. Police bton : instruction, listing, texte saisir. : dans les scripts, indique un retour la ligne volontaire d aux contraintes de la mise en page.
Il sagit dinformations complmentaires relatives au sujet trait. Propose conseils et trucs pratiques.
Sommaire
1
Le langage XAML 22
1.1 1.2
Introduction .................................................................... 24 Les bases de XAML ........................................................... 24 Hritage de XML ............................................................... 24 Adaptation de XML ........................................................... 25 Les lments de structure ................................................... Grid .............................................................................. StackPanel ...................................................................... Canvas .......................................................................... ScrollViewer .................................................................... Border ........................................................................... Les lments de contenu .................................................... Images ........................................................................... TextBlock ........................................................................ ProgressBar ..................................................................... Les lments dinteractions ................................................. Button ............................................................................ CheckBox ....................................................................... ToggleButton .................................................................... RadioButton ..................................................................... TextBox .......................................................................... PasswordBox ................................................................... ListBox et ListBoxItem .......................................................... ComboBox et ComboBoxItem .............................................. Slider ............................................................................. Autres lments utiles ........................................................ Line ............................................................................... Rectangle ....................................................................... Popup ............................................................................ Premire approche du DataBinding ..................................... DataTemplates ................................................................. ValueConverter ................................................................ Le chier Generic.XAML ..................................................... Rednir la structure dune ListBox .......................................... 26 26 30 31 32 33 35 35 36 37 40 40 42 43 45 46 47 47 49 51 51 51 52 53 55 61 66 72 72
1.3
1.4
1.5 1.6
1.7
1.8
1.9
Sommaire
1.10 1.11 2
Animez votre application grce aux StoryBoard .................... 79 Crez une bannire Silverlight grce aux animations ................. 82 Check-List ....................................................................... 95
96
Introduction Expression Studio ......................................... 98 Expression Design ............................................................ 99 Expression Encoder 2 ..................................................... 102 Expression Blend 2 ......................................................... 104 Intraction entre Expression Blend et Visual Studio 2008 ....... 109 Check-List ..................................................................... 111
112
3.1
Utilisez SQL et votre base de donnes ................................ Silverlight, C# et SQL Serveur : introduction ........................... SQL ............................................................................. Les commandes SQL en C# ...............................................
Exploitez vos donnes sur Oracle ...................................... 120 MySQL et Silverlight ....................................................... 124 LINQ ........................................................................... 126 LINQ, un peu dexplication ............................................... 129 LINQ to XML par lexemple ................................................ 129 Les Web services ........................................................... 134 ADO.NET/Silverlight ..................................................... 143 Crez un widget mto ................................................... 153 MapCodesToConditions ................................................... 170 Traitez un ux de donnes RSS ......................................... 174 Check-list ..................................................................... 179
180
Silverlight et ASP.NET
4.1
Introduction ASP.NET ................................................... 182 ASP.NET ....................................................................... 182 Prrequis ...................................................................... 183
Sommaire
Premier exemple ............................................................. 183 Le Web.cong ............................................................... 190 4.2 Les contrles ASP.NET ..................................................... Les contrles standard ...................................................... Les contrles de validation ................................................. Les contrles riches .......................................................... Les contrles de donnes .................................................. Les contrles de navigation ................................................ Les contrles de login ....................................................... Les contrles HTML .......................................................... Postback et ViewState ...................................................... Les contrles ASP.NET pour Silverlight ................................ Le contrle MediaPlayer ................................................... MediaPlayer et JavaScript ................................................. Le contrle Silverlight ........................................................ 191 191 192 193 193 195 196 197 197 198 201 205 207
4.3
4.4 4.5 5
Concepts avancs
5.1
Le DataBinding en dtails ................................................ 214 DataContext .................................................................. 216 Interaction avec lutilisateur ................................................ 218 Les Styles et ControlTemplates ........................................... 220 Style ............................................................................ 220 ControlTemplate ............................................................. 222 Crer un UserControl ...................................................... UserControl ClickMe ....................................................... UserControl Ranking ........................................................ Les DependencyProperties ................................................. Cration de lUserControl Ranking ....................................... MediaElement ................................................................ Les contrles de la librairie System.Windows.Controls .......... Calendar ...................................................................... DatePicker .................................................................... GridSplitter .................................................................... TabControl et TabItem ...................................................... 225 226 227 228 229 237 246 247 249 251 252
5.2
5.3
5.4
Le contrle DataGrid ...................................................... 253 DataGrid non auto gnr ................................................ 255 Les contrles Silverlight Toolkit de CodePlex ........................ 269 Check-list ..................................................................... 271
Sommaire
Dcouvrir Deepzoom
272
Introduction Deepzoom ................................................ 274 Fonctionnement de Deepzoom ......................................... 275 Deepzoom par lexemple ................................................ 279 MouseWheelHelper.cs ..................................................... 285 Deepzoom et Virtual Earth ............................................... 288 Check-list ..................................................................... 289
290
Annexes
7.1
Silverlight et les langages dynamiques ............................... Silverlight et IronPyhton ..................................................... Silverlight et IronRuby ....................................................... Check-list ...................................................................... Introduction au C# ......................................................... Dclaration dune variable de type primitif ............................. Rgles de nommage ........................................................ Dclaration dune variable de type de classe ......................... Fonctionnement par rfrence des types de classe ................... Porte des variables ........................................................ Utilisation des proprits de classe ...................................... Utilisation des mthodes de classe ....................................... Structure dun programme C# (Partie 1) ................................ Dnir un type de classe ................................................... Dnir une nouvelle mthode ............................................. Ajouter une mthode une classe ....................................... Structure dun programme C# (Partie 2) ................................ Exemple dune application de gestion de donnes .................. Conclusion .................................................................... Check-list ...................................................................... Webographie ............................................................... Visual Studio 2008 ......................................................... Silverlight ...................................................................... Le Framework .NET .........................................................
292 292 297 299 299 300 300 301 301 302 303 303 303 304 305 306 306 307 311 311 311 312 312 313
315
7.2
7.3
Index
Remerciements
Nous remercions les personnes qui nous ont aid la ralisation de ce livre et en particulier Stphanie Fanara qui sest propose comme premire relectrice de louvrage. Bargelot (Loc Bar et Simon Boigelot)
Prface
Dnition de Silverlight
Microsoft Silverlight est une plateforme de dveloppement dapplications web de haute qualit (RIA : rich Internet application). Cette plateforme est base sur la plateforme .NET, ce qui en fait la plateforme la plus rapide disponible sur Internet actuellement. Malgr leur dveloppement en .NET, les applications Silverlight sont portables. Autant sur Linux, Solaris, Windows et Mac Os que sur certains mobiles. Pour ce faire, le client web doit installer sur sa machine un sous-ensemble de la plateforme .NET : le plugin Silverlight. Ce sous-ensemble contient tout ce qui est ncessaire au fonctionnement de petites applications.
11
Prface
Pour accder une approche de la programmation .NET grce C#, reportez-vous lannexe 2, Introduction au C#.
une machine virtuelle capable dexcuter un code intermdiaire propre la plateforme ; un ensemble de langages parmi lesquels C#, VB.NET, ASP.NET, PHP.NET, IronPython, IronRuby, etc. ; un ensemble de librairies fournissant un grand nombre dAPI prprogrammes.
La version actuelle de la plateforme est 3.5. Au dbut, prvue pour la cration dapplications de bureautiques et de serveurs, cette plateforme sest peu peu dveloppe pour les sites web et les mobiles. De nombreux paradigmes de programmation accompagnent ce Framework. Le plus connu tant celui de la sparation du code dinterface et du code de la logique applicative. La majorit des langages implments par la plateforme divise le code dune application en deux chiers spars. Ce paradigme permet principalement une meilleure collaboration entre programmeurs, designers et intgrateurs. Parmi les librairies fournies, vous trouverez tout ce qui concerne les accs chier, les protocoles de communication, la gestion des donnes, les connexions aux bases de donnes, etc. Chaque nouvelle version du Framework ajoute une couche dabstraction qui rapproche le langage programm du langage humain. Ainsi la version 3.5 a ajout les requtes LINQ permettant de simplier grandement le maniement des donnes. La version 4, en beta actuellement, simpliera principalement laccs aux langages dynamiques. Entre autres, une librairie nomme DLR (Dynamic Langage Runtime) va permettre aux dveloppeurs de crer de nouveaux langages ou de migrer des langages existant sur la plateforme .NET.
12
Prface
Fonctionnement de Silverlight
Pour faire tourner une application Silverlight dans le navigateur web dun utilisateur, cet utilisateur doit pralablement installer un plugin. Ce plugin contient une machine virtuelle prte interprter le code XAML et certaines librairies de la plateforme .NET. Une fois install, et lors de la visite dune page HTML contenant un contrle Silverlight, le plugin va en tlcharger le contenu. Ce contenu est un chier XAP. Un chier XAP est un chier ZIP contenant tout les documents ncessaires au bon fonctionnement dune application Silverlight. Ces documents sont principalement :
j j j j
les diffrents chiers XAML, dcrivant les interfaces de lapplication ; les diffrents chiers C# (ou autre langage) dcrivant la logique applicative ; les ventuels mdias (images, vidos, musique, polices de caractres) ; des librairies .NET non prsentes dans le plugin Silverlight de base.
Lapplication va ensuite tre excute dans une zone mmoire de lordinateur client. Cette zone est une zone scurise du nom de SandBox (bac sable). Le bac sable empche lapplication Silverlight de nuire la machine hte. Par exemple, en limitant laccs aux chiers. Une application Silverlight garde tout de mme la possibilit dcrire et de lire des chiers sur lordinateur de lutilisateur. Cependant, cette fonctionnalit est limite en taille et demande lapprobation pralable de lutilisateur. Ce mme principe sapplique, par exemple, aux accs aux services web. La version 1.0 de Silverlight permettait lutilisation :
j j j j
des graphique 2D ; danimations ; de mdia ; dun code JavaScript comme code applicatif.
La version 1.1 permis lutilisation de code C# ainsi que de quelques autres langages du Framework.
13
Prface
La version 2.0, dernire en date, prsente dans ce livre, a ajout de nombreuses simplications dans lcriture du code XAML, de nouveaux contrles utilisateur et une version encore plus rapide du runtime.
14
Prface
Le premier cran ouvert dans Visual Studio est la page de dmarrage. Cette page vous donne un accs rapide aux dernires solutions ouvertes, aux actions de cration et douverture dautres solutions ainsi quau dernier post intressant du Web. La partie en haut se nomme la barre de menu, la partie place lextrmit droite contient deux outils : lExplorateur de solution et lditeur de proprits. Si ces outils ne sont pas visibles sous votre conguration actuelle de Visual Studio, vous pouvez les activer via le menu Affichage de la Barre de menu.
c Fig. 2 : Menu Affichage
Dans la bote de dialogue qui saffiche, naviguez vers le type de projet Visual C# Silverlight.
15
Prface
Slectionnez le modle Application Silverlight. 4 Donnez un nom votre application et cliquez sur OK.
3 c Fig. 5 : Bote de dialogue type de dbogage
Une nouvelle bote de dialogue souvre. Elle vous demande si vous dsirez gnrer un projet contenant un site web pour hberger votre application Silverlight immdiatement ou si vous prfrez que Visual Studio se charge de cette tche chaque dmarrage dune session de dbogage de votre application. 6 Ajoutez un nouveau projet ASP.NET la solution pour hberger Silverlight.
5
16
Prface
Les trois seuls chiers qui nous importent pour le moment sont :
j j j
Page.xaml contenant la dnition de linterface de votre application ; Page.xaml.cs qui dtient la dnition du code application de votre application ; NomDeLApplicationTestPage.aspx, page ASP.NET hte de votre SilverLight.
17
Prface
Compiler un projet
1
Pour dboguer un projet Silverlight, cliquez sur le bouton Play situ dans la barre doutils juste au-dessous de la Barre de menu (ou appuyez sur [F5]).
c Fig. 8 : Bouton Dboguer
Aprs compilation russie, votre projet sera lanc dans une page Internet Explorer. Si une erreur survient, la liste derreurs prsente en bas de Visual Studio vous en informera.
18
Prface
Lors de la premire excution de votre application, il est probable que vous trouviez la bote de dialogue Dbogage non activ.
c Fig. 10 : Dbogage non activ
Choisissez loption Modier le chier Web.cong pour activer le debogage et cliquez sur OK sans vous en soucier davantage.
Aprs avoir cr une solution Visual Studio 2008 contenant un projet Silverlight et un projet ASP.NET destins aux tests, ouvrez le chier Page.xaml.
Page.xaml
<UserControl x:Class="HelloWorld.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> </Grid> </UserControl>
Du code y est dj prsent, il sagit de code XAML, nous tudierons ce langage en dtails aux chapitres 2 et 5.
19
Prface
<UserControl x:Class="HelloWorld.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <TextBlock Text="HelloWorld" FontFamily="Verena" FontSize="70" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </UserControl> 3
Lancez lapplication.
c Fig. 11 : HelloWorld
20
Prface
Nous tudierons ensuite diffrentes mthodes daccs aux donnes, quelle quen soit leur provenance. Il sera alors temps de revenir sur nos bases de XAML pour en apprendre davantage. Pour nir, nous verrons comment intgrer au mieux Silverlight au sein dune application ASP.NET.
21
1
1.1 Introduction .............................................. 1.2 Les bases de XAML ..................................... 1.3 Les lments de structure ............................... 1.4 Les lments de contenu ............................... 1.5 Les vnements et leur traitement ...................... 1.6 Les lments dinteractions ............................. 1.7 Autres lments utiles ................................... 1.8 Premire approche du DataBinding .................. 1.9 Colorez votre application grce aux Brushes et aux Gradients ................................................ 1.10 Animez votre application grce aux StoryBoard .... 1.11 Check-List ................................................ 24 24 26 35 38 40 51 55 73 79 95
Le langage XAML
L
ors de la cration du Framework 3.0, Microsoft a mis un point dhonneur simplier linteraction entre les dveloppeurs, les intgrateurs et les designers lors du processus de dveloppement dune application. XAML (Extensible Application Markup Language) est la cl de vote de cette simplication concernant Windows Presentation Foundation.
Le langage XAML
1.1 Introduction
Linterface dune application y est dnie, ou dessine, sous la forme dun arbre XML. On retrouve dans cette mthode de dveloppement une approche trs proche de ce qui se fait depuis longtemps en ASP.NET, avec dun ct le code HTML, agrment de contrle ASP.NET, et de lautre, un code de logique applicative contenant la logique de lapplication. De nombreux outils tels que Expression Blend vous permettent de faire abstraction du XAML en vous proposant une interface interactive de dnition de votre application. Cependant, en tant que dveloppeur, une bonne connaissance du XAML vous aidera souvent. En effet, certaines opportunits offertes par Silverlight sont bien plus dpendantes du XAML que du code applicatif. Le binding en est un bon exemple.
Un document contient toujours un unique lment appel lment racine. Un lment est une suite de caractres respectant une nomenclature prcise. Un lment peut contenir des attributs et/ou des lments enfants.
Le premier caractre dun lment est toujours <. Le nom de llment suit directement. Viennent ensuite les diffrents attributs sous la forme NomDeLattribut= valeur . Les derniers caractres de llment sont />.
On obtient donc : <Nom [Attribut1= valeur [Attribut2= valeur []]]/>. Lorsque llment a des enfants, la suite de caractres fermants /> est remplace par >[enfants]</NomDeLlment>.
24
Adaptation de XML
En XAML, le nom de llment est remplac par le nom de la classe du contrle utilisateur quil reprsente. Ainsi, on peut ajouter un bouton notre interface de la manire suivante :
<Button/>
Ce bouton peut avoir des attributs, tels quune taille et un nom (ce qui permettra de le retrouver plus tard dans le code de la logique applicative).
<Button Width="100" Name="Button1"/>
En XAML, tout attribut peut tre transform en enfant. Cette particularit nous sera trs utile pour dclarer des attributs structurs :
<Button> <Button.Width>100</Button.Width> <Button.Name>Button1</Button.Name> </Button>
Tout contrle utilisateur est capable de contenir dautres contrles utilisateur. Ainsi, lemploi le plus frquent du contenu dun bouton est du texte :
<Button Content="du texte"> <Button.Width>100</Button.Width> <Button.Name>Button1</Button.Name> </Button> c Fig. 1.1 : Bouton contenant du texte
Mais il peut en tre autrement. Par exemple, voici un bouton contenant un autre bouton :
<Button Width="100" Name="Button1"> <Button Width="80" Name="Button2" Content="un autre btt"/> </Button> c Fig. 1.2 : Bouton contenant un autre bouton
Attention, la majorit des contrles utilisateur naccepte quun enfant. Il est donc impossible dcrire directement :
25
Le langage XAML
<Button Width="100" Name="Button1"> <Button Width="80" Name="Button2" Content="un autre btt"/> <Button Width="80" Name="Button3" Content="un autre btt"/> </Button>
Pour obtenir un rsultat de ce genre, il est indispensable dutiliser un des lments de Layout que nous verrons au chapitre 3, Crer vos applications avec Expression Studio. Il existe trois types dattributs diffrents :
j j j
Le premier type se trouve partout ou presque, tels Width et Height qui permettent de dnir la taille dun lment dinterface. Le deuxime type est un attribut qui se retrouve seulement dans un lment. Un attribut du deuxime type ne pourra jamais tre utilis dans un autre lment. Le troisime type dattribut est plus subtil. Un attribut de ce type appartient un lment mais est utilis dans un autre. Un bon exemple est lattribut Top de llment Canvas :
Attribut de troisime type
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="200"> <Canvas x:Name="LayoutRoot" Background="White"> <Button Canvas.Top="50"/> </Canvas> </UserControl>
26
Une grille peut tre compare un tableau compos de lignes et de colonnes. Chaque lment quelle contient doit lui spcier sa position. Le comportement de base dune grille stipule quelle est compose dune cellule unique. Cette cellule tentera de donner son contenu la taille maximale possible :
Comportement dune Grid sans cellules
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Button Content="Hello World"/> </Grid> </UserControl> c Fig. 1.3 : Comportement dune Grid sans cellules
Il est pourtant possible de stipuler une grille le nombre de colonnes quelle doit afficher. Sans autres informations, chaque colonne aura une taille gale aux autres. Il est maintenant devenu indispensable, pour le bouton contenu dans la grille, de prciser sa position :
Comportement dune Grid avec ColumnDenitions
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions>
27
Le langage XAML
28
Trois options soffrent nous pour forcer les diffrentes lignes ou colonnes adopter des tailles diffrentes :
j j j
en leur donnant une taille en pixels (Width=100) ; en leur demandant de prendre la taille de leur contenu (Width=Auto) ; en leur allouant une partie de lespace restant (Width=*).
Variation de tailles sur les ColumnDenitions et les RowDenitions
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="100"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="2*"/> </Grid.RowDefinitions> <Button Grid.Column="0" Grid.Row="0" Content="0,0"/> <Button Grid.Column="1" Grid.Row="0" Content="1,0"/> <Button Grid.Column="2" Grid.Row="0" Content="2,0"/> <Button Grid.Column="3" Grid.Row="0" Content="3,0"/>
29
Le langage XAML
<Button <Button <Button <Button <Button <Button <Button <Button <Button <Button <Button <Button </Grid> </UserControl>
Grid.Column="0" Grid.Column="1" Grid.Column="2" Grid.Column="3" Grid.Column="0" Grid.Column="1" Grid.Column="2" Grid.Column="3" Grid.Column="0" Grid.Column="1" Grid.Column="2" Grid.Column="3"
Grid.Row="1" Grid.Row="1" Grid.Row="1" Grid.Row="1" Grid.Row="2" Grid.Row="2" Grid.Row="2" Grid.Row="2" Grid.Row="3" Grid.Row="3" Grid.Row="3" Grid.Row="3"
Content="0,1"/> Content="1,1"/> Content="2,1"/> Content="3,1"/> Content="0,2"/> Content="1,2"/> Content="2,2"/> Content="3,2"/> Content="0,3"/> Content="1,3"/> Content="2,3"/> Content="3,3"/>
StackPanel
Le deuxime lment de la famille des Layout est le StackPanel. Un StackPanel imbrique ses diffrents enfants les uns au-dessous des autres :
StackPanel
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="100"> <Grid x:Name="LayoutRoot" Background="White"> <StackPanel> <Button Content="Hello"/> <Button Content="World"/> <Button Content="!!!"/>
30
Les lments fournis dans la plateforme Silverlight de base ne proposent pas de WrapPanel tel quon en trouve en WPF. Il existe deux solutions pour pallier ce problme :
j
utiliser le Silverlight ToolKit de CodePlex que nous voquerons plus tard ; Pour obtenir plus de renseignements sur le Silverlight Toolkit de CodePlex, reportez-vous au chapitre 5, Silverlight et ASP.NET.
<StackPanel Orientation="Horizontal"> <Button Content="Hello"/> <Button Content="World"/> <Button Content="!!!"/> </StackPanel> c Fig. 1.8 : StackPanel orientation horizontale
Canvas
Le dernier lment de la famille des Layout prsent dans ce livre est le Canvas. Son utilisation est la mme qu lpoque des WinForm. En effet, le Canvas, contrairement aux autres Layout, dlgue le positionnement de ses enfants eux-mmes. Ce positionnement est relatif leurs distances par rapport au dessus et la gauche du Canvas :
31
Le langage XAML
Canvas
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <Canvas x:Name="LayoutRoot" Background="White" > <Button Canvas.Top="0" Canvas.Left="0" Content="0,0"/> <Button Canvas.Top="100" Canvas.Left="100" Content="Hello"/> <Button Canvas.Top="130" Canvas.Left="130" Content="World"/> <Button Canvas.Top="160" Canvas.Left="160" Content="!!!"/> </Canvas> </UserControl> c Fig. 1.9 : Exemple de Canvas
ScrollViewer
Bien que le ScrollViewer ne soit pas proprement parler un lment de Layout, il permet tout de mme de structurer linterface. Cest lui qui vous offre lopportunit dajouter des ascenseurs votre application, quils soient horizontaux ou verticaux. Sans conguration, seul lascenseur vertical est visible :
ScrollViewer sans conguration
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <ScrollViewer x:Name="LayoutRoot" Background="White" > </ScrollViewer> </UserControl>
32
Les attributs HorizontalScrollBarVisibility et VerticalScrollBarVisibility permettent de modier cette conguration. Ils acceptent 4 valeurs diffrentes :
j j j j
Auto : lascenseur est visible uniquement si le contenu du ScrollViewer dpasse la taille du ScrollViewer. Disabled : lascenseur est visible mais inutilisable par lutilisateur. Hidden : lascenseur est cach. Visible : lascenseur est toujours visible. Si la taille du contenu dpasse la taille du ScrollViewer, lascenseur pourra tre employ par lutilisateur.
ScrollViewer avec conguration
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <ScrollViewer x:Name="LayoutRoot" Background="White" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> </ScrollViewer> </UserControl>
Border
Au mme titre que le ScrollViewer, llment Border nest pas un lment de Layout. Cependant, son utilisation permet de rendre plus comprhensible la structure dune interface pour lutilisateur. Un Border est seulement une ligne qui entoure llment quil contient. Ses diffrents attributs lui donnent une exibilit incomparable et font de lui un atout majeur :
33
Le langage XAML
Margin="5" BorderBrush="Black" Background="Aqua"> <TextBlock Text="Border with Background" Margin="5"/> </Border> </StackPanel> </UserControl> c Fig. 1.11 : Diffrents exemples de Border
34
35
Le langage XAML
Un des attributs les plus importants de llment Image est lattribut Stretch. Il permet de dnir comment llment va interagir avec limage pour lafficher, sil va la redimensionner, la couper, en conserver les proportions dorigine ou non.
TextBlock
Le TextBlock est la zone de texte la plus communment utilise. Elle permet de choisir toutes les caractristiques habituelles dun texte, de sa famille sa taille, en passant par sa couleur :
TextBlock
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <StackPanel x:Name="LayoutRoot" Background="White"> <TextBlock Text="texte blablabla" TextAlignment="Center" TextWrapping="NoWrap" FontFamily="Arial" FontSize="24" FontStyle="Italic"
36
FontWeight="Bold" Foreground="Blue"/> <TextBlock Text="texte 2" TextAlignment="Left" TextWrapping="NoWrap" FontFamily="Verena" FontSize="13" FontWeight="Bold" Foreground="Red"/> <TextBlock Text="texte 3" TextAlignment="Right" TextWrapping="NoWrap" FontFamily="Verena" FontSize="17" FontWeight="Bold" Foreground="Magenta"/> </StackPanel> </UserControl> c Fig. 1.15 : Exemple de TextBlocks
Remarquez lattribut TextWrapping. Il permet de passer automatiquement la ligne lorsque sa valeur est Wrap. Le cas chant, si la longueur du texte dpasse la taille du TextBlock, le surplus sera coup.
ProgressBar
Comme son nom lindique, la ProgressBar sert indiquer ltat dune progression, il sagit de la mme ProgressBar que celle utilise par Windows lors dune copie. Son attribut Value indique ltat actuel de la progression qui peut varier de Minimum Maximum :
ProgressBar
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="300" Height="30">
37
Le langage XAML
<StackPanel x:Name="LayoutRoot" Background="White"> <ProgressBar Name="ProgressBar1" Height="30" Maximum="100" Value="40" Minimum="0" Foreground="Green" /> </StackPanel> </UserControl> c Fig. 1.16 : ProgressBar
Code C#
using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows;
38
namespace LearnXAML { public partial class Page : UserControl { public Page() { InitializeComponent(); string temp = "" + Boutton1.Content; } } }
Pour ajouter lvnement Clic sur ce bouton, indiquez-le comme attribut dans le code XAML et ajoutez la fonction relative dans le code C#. Gnralement, cette opration est automatique :
Modication du code XAML
<Button Name="Boutton1" Content="un boutton" Clic="Boutton1_Clic"/>
Modication du code C#
using namespace LearnXAML { public partial class Page : UserControl { public Page() {} private void Boutton1_Clic(object sender, RoutedEventArgs e) { Boutton1.Content = "Merci"; } } }
39
Le langage XAML
Les vnements relatifs aux entres utilisateur sont partags par la majorit des lments dinterface. Ainsi MouseEnter, MouseMove, MouseLeftButtonDown, MouseLeftButtonUp, MouseLeave, KeyUp et KeyDown se retrouvent presque partout.
Absence de clic droit en Silverlight
En Silverlight, il ny a pas dvnements lis au clic droit de la souris.
Le texte dun bouton est dni dans son attribut Content. En effet, ce contenu peut tre autre chose que du texte. Par exemple, une image :
Bouton avec une image comme contenu
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML"
40
Width="100" Height="100"> <Grid x:Name="LayoutRoot" Background="White"> <Button Clic="Boutton1_Clic"> <Image Source="wipuslogo.jpg" Stretch="UniformToFill"/> </Button> </Grid> </UserControl> c Fig. 1.18 : Bouton avec une image comme contenu
Ou quelque chose de plus complexe tel quune grille contenant plusieurs images et un autre bouton :
Bouton contenu htroclite
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <Grid x:Name="LayoutRoot" Background="White"> <Button Clic="Boutton1_Clic"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Image Grid.Row="0" Grid.Column="1" Source="wipuslogo.jpg" Stretch="UniformToFill"/> <Image Grid.Row="0" Grid.Column="0" Source="wipuslogo.jpg" Stretch="UniformToFill"/> <Image Grid.Row="1" Grid.Column="1" Source="wipuslogo.jpg"
41
Le langage XAML
Stretch="UniformToFill"/> <Button Grid.Row="1" Grid.Column="0" Content="Un autre"/> </Grid> </Button> </Grid> </UserControl> c Fig. 1.19 : Bouton contenu htroclite
CheckBox
Une CheckBox est une bote deux ou trois tats selon sa conguration. Son tat peut tre coch, non coch ou ventuellement inconnu. Cet tat est stock sous forme dun boolen annulable dans lattribut IsChecked. Lattribut IsThreeState permet de dnir si la CheckBox peut ou non passer par ltat inconnu :
Exemple de CheckBox
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="50"> <StackPanel x:Name="LayoutRoot" Background="White"> <CheckBox IsChecked="False" Content="Not Checked CheckBox"/>
42
<CheckBox IsChecked="True" Content="Checked CheckBox"/> <CheckBox IsThreeState="True" IsChecked="{x:Null}" Content="Null Checked CheckBox"/> </StackPanel> </UserControl> c Fig. 1.20 : Exemple de CheckBox
Lorsquune CheckBox passe dun tat un autre, les vnements Checked et UnChecked sont dclenchs :
Evnements Checked et UnChecked (XAML)
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="50"> <StackPanel x:Name="LayoutRoot" Background="White"> <CheckBox IsChecked="False" Content="CheckBox" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"/> </StackPanel> </UserControl>
ToggleButton
Un ToggleButton est une CheckBox sous forme de bouton. Son tat peut tre enfonc, non-enfonc ou ventuellement inconnu. Cet tat est stock sous forme dun boolen annulable dans lattribut IsChecked.
43
Le langage XAML
Lattribut IsThreeState permet de dnir si le ToggleButton peut ou non passer par ltat inconnu :
Exemple de ToggleButton
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="90"> <StackPanel x:Name="LayoutRoot" Background="White"> <ToggleButton Height="30" Content="ToggleButton1" IsChecked="False"/> <ToggleButton Height="30" Content="ToggleButton2" IsChecked="True"/> <ToggleButton Height="30" Content="ToggleButton3" IsThreeState="True" IsChecked="{x:Null}"/> </StackPanel> </UserControl> c Fig. 1.21 : Exemple de ToggleButton
Lorsque ltat dun ToggleButton change, les vnements Checked et UnChecked sont dclenchs :
Evnements dtat dun ToggleButton
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="90"> <StackPanel x:Name="LayoutRoot" Background="White"> <ToggleButton Height="30" Content="ToggleButton1" IsChecked="False" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked"/> </StackPanel> </UserControl>
44
RadioButton
Les RadioButtons fonctionnent de la mme faon que les ToggleButtons. Eux aussi possdent les attributs IsChecked, IsThreeState, Content, etc. Cependant, ils offrent une fonctionnalit supplmentaire les rendant intressants : lattribut GroupName. Parmi un ensemble de plusieurs RadioButtons partageant le mme GroupName, seul un RadioButton pourra avoir son tat IsCheked vrai. Si un autre de ces RadioButtons passe ltat Checked, automatiquement, le prcdent RadioButton Checked deviendra UnChecked :
Exemple de RadioButtons
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="130"> <StackPanel x:Name="LayoutRoot" Background="White"> <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Margin="5"> <StackPanel> <RadioButton GroupName="Group1" Content="Radio1.1"/> <RadioButton GroupName="Group1" Content="Radio1.2" IsChecked="True"/> <RadioButton GroupName="Group1" Content="Radio1.3"/> </StackPanel> </Border> <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Margin="5"> <StackPanel> <RadioButton GroupName="Group2" Content="Radio2.1" IsChecked="True"/> <RadioButton GroupName="Group2" Content="Radio2.2"/> <RadioButton GroupName="Group2" Content="Radio2.3"/> </StackPanel> </Border> </StackPanel> </UserControl>
45
Le langage XAML
De mme que pour le ToggleButton, les vnements Checked et UnChecked sont dclenchs lorsquun RadioButton change dtat.
TextBox
lment de saisie de texte, une TextBox offre les mmes attributs quun TextBlock :
Exemple de TextBox
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="30"> <StackPanel x:Name="LayoutRoot" Background="White"> <TextBox FontFamily="Arial" Foreground="Black" Text="(Please insert text here)" Margin="5" TextChanged="TextBox_TextChanged"/> </StackPanel> </UserControl> c Fig. 1.23 : Exemple de TextBox
Lvnement TextChanged est dclench lorsque lutilisateur a ni dditer le texte contenu dans la TextBox. Cela tant, hormis pour une validation, le texte entr par lutilisateur sera utilis lors dun autre vnement, tel que le clic sur un bouton adjacent. Pour rcuprer le texte contenu dans ce TextBox partir du code C#, il suffit den utiliser la proprit Text.
46
PasswordBox
Une PasswordBox est une TextBox naffichant pas les caractres frapps au clavier mais des caractres de remplacements :
Exemple de PasswordBox
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="30"> <StackPanel x:Name="LayoutRoot" Background="White"> <PasswordBox FontFamily="Arial" Foreground="Black" Password="(Please insert text here)" Margin="5" PasswordChanged="PasswordBox_PasswordChanged" PasswordChar="*"/> </StackPanel> </UserControl> c Fig. 1.24 : Exemple de PasswordBox
Attention, le texte contenu dans une PasswordBox porte le nom de Password et non de Text. Il en va de mme pour la proprit dans le code C#. Lattribut PasswordChar donne au dveloppeur lopportunit de choisir un caractre de remplacement diffrent de celui de la plateforme dorigine.
ListBox et ListBoxItem
La ListBox est un lment compos dun StackPanel et dun ScrollViewer. Mais ce nest pas tout, elle implmente dorigine une interface lui permettant de grer une collection ditems slectionnables :
ListBox contenant des ListBoxItems
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <Grid x:Name="LayoutRoot" Background="White"> <ListBox>
47
Le langage XAML
Les lments utiliss dans cet exemple comme items sont des ListBoxItems. Bien que les ListBoxItems soient prvus spcialement pour servir ditems dans une ListBox, tout autre lment de la plateforme peut les substituer. Ainsi, il est possible davoir une ListBox contenant comme items des boutons, des autres ListBox, des lments de Layout contenant eux-mmes dautres lments enfants, etc. :
ListBox contenant des lments htroclites
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="200"> <Grid x:Name="LayoutRoot" Background="White"> <ListBox> <Button Content="ListBoxItem1"/> <ListBox> <ListBoxItem Content="ListBoxItem2.1"/> <ListBoxItem Content="ListBoxItem2.2"/> </ListBox> <StackPanel Orientation="Horizontal"> <ListBoxItem Content="ListBoxItem3.1"/> <Button Content="ListBoxItem3.1"/> </StackPanel> <ListBoxItem Content="ListBoxItem4"/> </ListBox> </Grid> </UserControl>
48
Lorsque la slection passe dun lment un autre, lvnement SelectedItemChanged est dclench.
ComboBox et ComboBoxItem
Une ComboBox est une ListBox prsente sous forme dune liste droulante. Son utilisation est donc semblable celle dune ListBox :
Exemple de ComboBox
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="40"> <Grid x:Name="LayoutRoot" Background="White"> <ComboBox Height="30" Margin="5"> <ComboBoxItem Content="ComboBoxItem1"/> <ComboBoxItem Content="ComboBoxItem2"/> <ComboBoxItem Content="ComboBoxItem3" IsSelected="True"/> <ComboBoxItem Content="ComboBoxItem4"/> </ComboBox> </Grid> </UserControl> c Fig. 1.27 : Exemple de ComboBox
Les lments utiliss dans cet exemple sont des ComboBoxItems, mais comme une ListBox, les ComboBox acceptent nimporte quels lments comme items.
49
Le langage XAML
Il est donc possible, par exemple, de construire une ComboBox dimages, de boutons et dinformations diverses runies :
Exemple de ComboBox contenu htroclite
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="40"> <Grid x:Name="LayoutRoot" Background="White"> <ComboBox Height="30" Margin="5"> <Image Source="wipuslogo.jpg" Height="100" Width="100" Stretch="UniformToFill"/> <Button Content="ComboBoxItem2"/> <StackPanel Orientation="Vertical"> <TextBlock Text="ComboBoxItem3" /> <Button Content="ComboBoxItem4"/> </StackPanel> <Image Source="http://www.wipus.com/WipusCloud.jpg" Height="100" Width="100" Stretch="UniformToFill"/> </ComboBox> </Grid> </UserControl> c Fig. 1.28 : Exemple de ComboBox contenu htroclite
Lorsque la slection passe dun lment un autre, lvnement SelectedItemChanged est dclench.
50
Slider
Un Slider est un curseur se dplaant le long dune ligne pour permettre lutilisateur dindiquer une valeur numrique de faon visuelle. La valeur (Value) indique par le curseur varie de lattribut Minimum gauche de la ligne lattribut Maximum droite de la ligne :
Exemple de Slider
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="40"> <Grid x:Name="LayoutRoot" Background="White"> <Slider Maximum="100" Minimum="0" Value="40" SmallChange="1" LargeChange="10" /> </Grid> </UserControl> c Fig. 1.29 : Exemple de Slider
Les attributs SmallChange et LargeChange reprsentent respectivement la valeur ajoute ou retire la valeur en cours lors dun dplacement par la souris ou le clavier. Lvnement ValueChanged est dclench lorsque la valeur indique par le curseur est modie par lutilisateur.
51
Le langage XAML
Exemple de Ligne
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="40"> <Grid x:Name="LayoutRoot" Background="White"> <Line X1="5" Y1="10" X2="195" Y2="30" Stroke="Black" StrokeThickness="3"/> <Line X1="5" Y1="30" X2="195" Y2="30" Stroke="Magenta" StrokeThickness="3"/> </Grid> </UserControl> c Fig. 1.30 : Exemple de ligne
Dans cet exemple, deux lignes sont dessines grce aux positions relatives (en pixels) de leurs points dorigine et de destination par rapport llment qui les contient. Ces deux points sont respectivement {X1,Y1} et {X2,Y2}.
Rectangle
Dans le mme ordre dides, un rectangle est dni par ses dimensions. Les attributs RadiusX et RadiusY, quant eux, permettent den arrondir les bords :
Exemple de Rectangle
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="60"> <StackPanel x:Name="LayoutRoot" Background="White"> <Rectangle Fill="Magenta" Margin="5" Height="20" Width="100" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"/> <Rectangle Fill="Blue" Margin="5" Height="20" RadiusX="30" RadiusY="30"/> </StackPanel> </UserControl>
52
Attention, un rectangle est un lment gomtrique et non un lment dinterface ; il naccepte donc pas de contenu. Le code suivant ne fonctionnera pas :
Rectangle avec contenu
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="60"> <StackPanel x:Name="LayoutRoot" Background="White"> <Rectangle Fill="Magenta" Margin="5" Height="20" Width="100" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"> <Button/> </Rectangle> </StackPanel> </UserControl>
Pour obtenir un rsultat semblable qui fonctionne, utilisez un Border avec Background.
Popup
En Silverlight, un lment Popup nest pas un popup proprement parler tel quon lentend dans le monde du Web. En effet, il ne sagit en aucun cas dune fentre supplmentaire qui souvre hors du navigateur dans lequel sexcute lapplication Silverlight. Un popup Silverlight nest rien dautre quun lment dinterface indpendant de la structure solide dnie par les lments de Layout de lapplication. Il saffiche librement au-dessus de tout autre contrle.
53
Le langage XAML
Dans cet exemple, un bouton contrle louverture dun popup. Ce popup contient comme lments enfants un texte et un bouton dclenchant sa fermeture :
Exemple de Popup (XAML)
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="200" Height="60"> <Grid x:Name="LayoutRoot" Background="White"> <Button Height="20" Width="100" Clic="OpenPopup" Content="Open Popup"/> <Popup Name="MyPopup" VerticalAlignment="Center" HorizontalAlignment="Center"> <Border BorderBrush="Black" BorderThickness="2" Background="Beige"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Text Popup" Margin="5"/> <Button Margin="5" Clic="ClosePopup" Content="x"/> </StackPanel> </Border> </Popup> </Grid> </UserControl>
Ce sont sur les vnements Clic des deux boutons que lon assignera une valeur diffrente lattribut IsOpen du popup. Lorsque cet attribut est vrai, le popup est affich :
Exemple de Popup (C#)
using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media;
54
using System.Windows.Media.Animation; using System.Windows.Shapes; namespace LearnXAML { public partial class Page : UserControl { public Page() { InitializeComponent(); } private void OpenPopup(object sender, RoutedEventArgs e) { MyPopup.IsOpen = true; } private void ClosePopup(object sender, RoutedEventArgs e) { MyPopup.IsOpen = false; } } }
55
Le langage XAML
Lapplication que nous allons raliser ici se doit de grer une liste dtudiants, rpartis dans plusieurs cours. Un tudiant est dni par son Nom, son Prnom et son ge :
Etudiant.cs
using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace LearnXAML { public class Etudiant { private string nom; public string Nom { get { return nom; } set { nom = value; } } private string prenom; public string Prenom { get { return prenom; } set { prenom = value; } } private int age; public int Age { get { return age; } set { age = value; } } public Etudiant() { }
56
} }
Un cours, quant lui, est dni par son Nom et comprend une liste dtudiants :
Cours.cs
using using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Collections.Generic;
namespace LearnXAML { public class Cours { private string nom; public string Nom { get { return nom; } set { nom = value; } } private List<Etudiant> etudiants; public List<Etudiant> Etudiants { get { return etudiants; } set { etudiants = value; } } public Cours() { } } }
57
Le langage XAML
Ajoutons au code applicatif de cette application la dclaration en dur dune liste de deux cours comprenant chacun quelques tudiants :
Dclaration en dure dune liste dtudiant
using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace LearnXAML { public partial class Page : UserControl { private List<Cours> ListeDeCours; public Page() { InitializeComponent(); #region HardCode ListeDeCours ListeDeCours = new List<Cours>() { new Cours() { Nom = "Declamation", Etudiants = new List<Etudiant>() { new Etudiant() {Prenom="Laurane", Nom="D.", Age=19 }, new Etudiant() {Prenom="Ma", Nom="H.", Age=18 }, new Etudiant() {Prenom="Dovy", Nom="F.", Age=21 } } }, new Cours() { Nom = "Sculpture", Etudiants = new List<Etudiant>() { new Etudiant() {Prenom="Adelade", Nom="A.", Age=19 },
58
new Etudiant() {Prenom="Klintes", Nom="T.", Age=20 }, new Etudiant() {Prenom="Kaphilis", Nom="A.", Age=20 }, new Etudiant() {Prenom="Jade", Nom="G.", Age=14 } } } }; #endregion HarCode ListeDeCours } } }
un cours de dclamation dont les lves sont Laurane, Ma et Dovy ; un cours de sculpture dont les lves sont Adelade, Klintes, Kaphilis et Jade.
Pour lier la liste de cours cette ListBox, il suffit dajouter dans le code applicatif, sous la dclaration en dur :
Ajout au code applicatif
CoursListBox.ItemsSource = ListeDeCours;
Cette ligne de code ordonne la ListeBox CoursListBox dafficher le contenu de la liste ListeDeCours.
59
Le langage XAML
Voici le rsultat :
c Fig. 1.33 : DataBinding direct
Bien que cela ne plante pas et que nous dtections dj 2 items diffrents dans cette ListBox, linterface obtenue est loin dtre satisfaisante pour un utilisateur nal. Pourquoi ? La plateforme .Net, en labsence dinformations lui dictant comment afficher un objet, en appelle la mthode ToString. Cette mthode, prsente intrinsquement dans chaque objet, retourne une chane de caractres comprenant le nom de la classe de cet objet. Le premier contournement de ce problme est donc la surcharge de cette mthode :
Ajout Cours.cs
public override string ToString() { string ret = this.nom; if(etudiants == null) return ret; ret += "\t("; foreach(Etudiant e in etudiants) ret += " "+e.Prenom; ret += " )"; return ret; }
60
Grce cette simple modication, notre affichage de donnes est dj bien plus agrable voir :
c Fig. 1.34 : DataBinding avec surcharge de ToString()
DataTemplates
Voici la faon la plus intressante de rendre lisible toute notre liste de cours ainsi que ses lves respectifs. Un DataTemplate est une structure XAML qui sera applique chacun des items dune ListBox donne. Ici le changement se fait uniquement dans le code XAML, lindpendance avec le code applicatif est parfaite. Ce qui permet de dlguer plus facilement ce travail aux designers et intgrateurs. La ListBox possde un attribut du nom de ItemTemplate qui permet de dnir quel Template utiliser pour afficher les items :
Exemple de DataTemplate 1
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <ListBox Name="CoursListBox"> <ListBox.ItemTemplate> <DataTemplate> <Border CornerRadius="2" Margin="3" BorderBrush="Black" BorderThickness="1"> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> </Border>
61
Le langage XAML
Pour prciser quelles proprits des objets forment la source du binding, il faut afficher. XAML offre une mthode de navigation par chane de caractres travers ces derniers. Ainsi le code {Binding Path=Nom} dans notre exemple, stipule que pour chaque Cours, linterface doit afficher la proprit Nom. En ce qui concerne la liste dlves, il faut ajouter ce DataTemplate une nouvelle liste, dont lItemSource est la proprit Etudiants de chaque cours :
Exemple de DataTemplate2
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <ListBox Name="CoursListBox"> <ListBox.ItemTemplate> <DataTemplate> <Border CornerRadius="2" Margin="3" BorderBrush="Black" BorderThickness="1"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <ListBox ItemsSource="{Binding Path=Etudiants}"/> </StackPanel> </Border> </DataTemplate> </ListBox.ItemTemplate>
62
Un nouveau DataTemplate doit ensuite tre cr, cette fois non pour les cours mais pour les tudiants :
Exemple de DataTemplate 3
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <ListBox Name="CoursListBox"> <ListBox.ItemTemplate> <DataTemplate> <Border CornerRadius="2" Margin="3" BorderBrush="Black" BorderThickness="1"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <ListBox ItemsSource="{Binding Path=Etudiants}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Prenom}" Margin="5"/> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <TextBlock Text="{Binding Path=Age}" Margin="5"/> </StackPanel>
63
Le langage XAML
</DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Border> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </UserControl> c Fig. 1.37 : Exemple de DataTemplate 3
Cette mthode donne un rsultat surprenant. Cependant, le code, lui, est des plus immondes. Lire un code XAML de ce genre est presque impossible ds quil grandit un peu. Rsoudre ce problme de clart invoque lutilisation des Ressources XAML. Chaque lment XAML a la possibilit dtre lhte dune collection de ressources. Ces ressources seront accessibles tous les lments enfants de llment hte grce leur nom. (En loccurrence, grce leur x:Key.) Le code XAML de lexemple prcdent, agrment de lutilisation des ressources, devient :
Exemple de DataTemplate en Ressources
<UserControl x:Class="LearnXAML.Page" xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML" Width="400" Height="300">
64
<UserControl.Resources> <DataTemplate x:Key="EtudiantDataTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Prenom}" Margin="5"/> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <TextBlock Text="{Binding Path=Age}" Margin="5"/> </StackPanel> </DataTemplate> <DataTemplate x:Key="CoursDataTemplate"> <Border CornerRadius="2" Margin="3" BorderBrush="Black" BorderThickness="1"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <ListBox ItemsSource="{Binding Path=Etudiants}" ItemTemplate="{StaticResource EtudiantDataTemplate}"/> </StackPanel> </Border> </DataTemplate> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <ListBox Name="CoursListBox" ItemTemplate="{StaticResource CoursDataTemplate}"/> </Grid> </UserControl>
Non seulement la lisibilit du code sest beaucoup amliore, mais en plus, ces DataTemplates sont maintenant rutilisables dautres endroits de notre interface, sans quon ait besoin de les copier.
Diffrence entre StaticResource et DynamicResource
Remarquez lutilisation du mot StaticResource. Une ressource statique est une ressource dnie dans le mme document et en amont de son utilisation. Ceci explique que EtudiantDatatTemplate soit dni avant CoursDataTemplate. Une alternative cette structure rigoureuse est dutiliser DynamicResource. Une ressource dynamique peut tre dnie nimporte o dans lapplication, mme dans un autre chier.
65
Le langage XAML
ValueConverter
Dans lexemple prcdent, une proprit C# est affiche telle quelle lors de son binding sur linterface. Ainsi, le nom Lauranne est pleinement lisible. Cependant ce nest pas toujours lidal. Si nous ajoutons la proprit EstDou de type booleen aux tudiants, le rsultat de son binding sera soit TRUE, soit FALSE :
Ajout Etudiant.cs
private bool estDou; public bool EstDou { get { return estDou; } set { estDou = value; } }
Comme il nest pas possible de surcharger cette mthode dans un type primitif, une autre solution soffre nous : un ValueConverter. Un ValueConverter est une classe C# qui, comme son nom lindique, transforme une valeur, quelle quelle soit, en une autre valeur. Ainsi dans le cas prsent, nous allons crire un ValueConverteur transformant la valeur TRUE en est un lve dou, et la valeur FALSE en nest pas un lve dou.
66
Linterface IValueConverter fait dune classe un ValueConverteur. Son implmentation demande deux mthodes :
j j
Convert convertit la valeur source en valeur afficher. ConvertBack convertit la valeur afficher en valeur source.
EstDouValueConverter.cs
using using using using using using using using using using using using
System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Windows.Data; System.Globalization;
namespace LearnXaml { public class EstDouValueConverter : IValueConverter { private const string Dou = "est un lve dou"; private const string NonDou = "nest pas un lve dou"; #region IValueConverter Membres public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { bool? EstDou = (value as bool?); if (EstDou == null || EstDou.HasValue == false) throw new InvalidCastException( "EstDouValueConverter.Convert value is not bool or is null"); if (EstDou.Value) { return Dou; } else { return NonDou;
67
Le langage XAML
} } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { string EstDou = value.ToString(); switch (EstDou) { case Dou: return true; case NonDou: return false; default: throw new InvalidCastException( "EstDouValueConverter.ConvertBack value incorrecte" + value.ToString()); } } #endregion } }
Pour utiliser le ValueConverter EstDouValueConverter dans un binding, plusieurs tapes doivent tre respectes :
j j
j j
ajouter le code du ValueConverter la solution Silverlight (ou en ajouter la rfrence dune assembly compile pralablement pour Silverlight) ; ajouter au chier XAML un using (xmls) pointant vers lespace de noms du ValueConverter (dans ce cas, lespace de noms est le mme que celui de lapplication mais cela peut varier) ; crer une instance de ce ValueConverter dans les ressources de lapplication ; spcier au binding dutiliser cette instance de ValueConverter.
Modication du chier XAML
68
<UserControl.Resources> <MyApp:EstDouValueConverter x:Key="estDouValueConverter"/> <DataTemplate x:Key="EtudiantDataTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Prenom}" Margin="5"/> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <TextBlock Text="{Binding Path=Age}" Margin="5"/> <TextBlock Text="{Binding Path=EstDou, Converter={StaticResource estDouValueConverter}}" Margin="5" /> </StackPanel> </DataTemplate> <DataTemplate x:Key="CoursDataTemplate"> <Border CornerRadius="2" Margin="3" BorderBrush="Black" BorderThickness="1"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <ListBox ItemsSource="{Binding Path=Etudiants}" ItemTemplate="{StaticResource EtudiantDataTemplate}"/> </StackPanel> </Border> </DataTemplate> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <ListBox Name="CoursListBox" ItemTemplate="{StaticResource CoursDataTemplate}"/> </Grid> </UserControl> c Fig. 1.39 : Binding avec ValueConverter
69
Le langage XAML
namespace LearnXaml { public class RatioValueConverter : IValueConverter { private int ratio = 5; public int Ratio { get { return ratio; } set { ratio = value; } }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (int)value * ratio; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
70
Il est alors possible dutiliser ce RatioConverter dans le code XAML pour, par exemple, transformer lge (en annes) des tudiants en un nombre de mois :
Modication du code XAML
<MyApp:EstDouValueConverter x:Key="estDouValueConverter"/> <MyApp:RatioValueConverter x:Key="AnneeEnMoisConverter" Ratio="12"/> <DataTemplate x:Key="EtudiantDataTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Prenom}" Margin="5"/> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> <TextBlock Text="{Binding Path=Age, Converter={StaticResource AnneeEnMoisConverter}}" Margin="5"/> <TextBlock Text="{Binding Path=EstDou, Converter={StaticResource estDouValueConverter}}" Margin="5" /> </StackPanel> </DataTemplate> c Fig. 1.40 : Binding avec RatioValueConverter
71
Le langage XAML
Le chier Generic.XAML
Comme nous le voyons dans lexemple suivi tout au long ce chapitre, le nombre de ressources de notre page XAML ne cesse de grandir. Pour viter un code trop long et rendre ces ressources accessibles depuis nimporte quel chier XAML de notre application, il suffit de crer un chier XAML du nom de Generic.XAML dans le dossier Themes de larborescence de la solution Silverlight.
c Fig. 1.41 : Arborescence de solution pour le chier Generic.XAML
Attention, dans les proprits du chier Generic.xaml, le mode de compilation doit tre chang de Page Resource.
72
73
Le langage XAML
De nombreux lments dinterface ont la possibilit dtre congurs pour utiliser dautres couleurs que leurs couleurs dorigines. Il sagit gnralement des attributs Background, Foreground, Stoke, BorderColor, etc. Mais il y a mieux, en plus daccepter des Brushes comme valeurs, ces attributs acceptent aussi des Gradients. Les Gradients sont des collections de couleurs et doffsets permettant de crer un dgrad. La classe Gradient est une classe abstraite dont dcoule quelques types de Gradients diffrents et ne pouvant tre utiliss directement en XAML.
LinearGradientBrush
Le type de Gradient le plus simple est le LinearGradiantBrush :
Exemple de LinearGradientBrush
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot"> <Grid.Background> <LinearGradientBrush> <GradientStop Offset="0" Color="White"/> <GradientStop Offset="1" Color="Black"/> </LinearGradientBrush> </Grid.Background> </Grid> </UserControl>
74
Le LinearGradientBrush est une fonction linaire dont les couleurs varient proportionnellement un offset. Dans ce cas, le pinceau va varier du blanc x = 0 au noir x = 100. Il est possible dajouter plus de couleurs dans un LinearGradientBrush la fonction est alors divise en un set de segments de taille suffisante pour afficher le dgrad selon les crits du XAML :
Exemple de LinearGradientBrush dcoup
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot"> <Grid.Background> <LinearGradientBrush> <GradientStop Offset="0" Color="White"/> <GradientStop Offset="0.3" Color="Black"/> <GradientStop Offset="0.5" Color="White"/> <GradientStop Offset="0.7" Color="Black"/> <GradientStop Offset="0.9" Color="Black"/> <GradientStop Offset="1" Color="White"/> </LinearGradientBrush> </Grid.Background> </Grid> </UserControl> c Fig. 1.45 : Exemple de LinearGradientBrush dcoup
75
Le langage XAML
Lorientation du dgrad, ici de gauche droite, est elle aussi modiable. Le dgrad commence son attribut StartPoint et nit son attribut EndPoint. Chacun de ces attributs sont des points dnis par deux valeurs : X et Y en pourcentage de llment colorier. En modiant un peu ces attributs, nous pouvons crer un dgrad vertical :
LinearGradientBrush vertical
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot"> <Grid.Background> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Offset="0" Color="White"/> <GradientStop Offset="1" Color="Black"/> </LinearGradientBrush> </Grid.Background> </Grid> </UserControl> c Fig. 1.46 : LinearGradientBrush vertical
RadialGradientBrush
Un RadialGradientBrush agit de la mme manire quun LinearGadientBrush mais en dcrivant des cercles :
Exemple de RadialGradientBrush
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot"> <Grid.Background> <RadialGradientBrush>
76
<GradientStop Offset="0" Color="White"/> <GradientStop Offset="0.3" Color="Black"/> <GradientStop Offset="0.5" Color="White"/> <GradientStop Offset="0.7" Color="Black"/> <GradientStop Offset="0.9" Color="Black"/> <GradientStop Offset="1" Color="White"/> </RadialGradientBrush> </Grid.Background> </Grid> </UserControl> c Fig. 1.47 : Exemple de RadialGradientBrush
Contrairement au LinearGradientBrush, ce sont les attributs Center et GradientOrigin qui permettent de changer la source et lorientation du dgrad :
RadialGradientBrush dcentr
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot"> <Grid.Background> <RadialGradientBrush Center="0.8,0.8" GradientOrigin="0.8,0.8"> <GradientStop Offset="0" Color="White"/> <GradientStop Offset="1" Color="Black"/> </RadialGradientBrush> </Grid.Background> </Grid> </UserControl> c Fig. 1.48 : RadialGradientBrush dcentr
77
Le langage XAML
ImageBrush
Les ImageBrushes vous permettent dutiliser une image la place dun Brush. On les emploie de la mme faon que llment Image :
Exemple de ImageBrush
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot"> <Grid.Background> <ImageBrush ImageSource="wipuslogo.jpg" Stretch="None"/> </Grid.Background> </Grid> </UserControl> c Fig. 1.49 : Exemple dImageBrush
Lutilit de ce genre de GradientBrush est vidente lorsquon lemploie sur des attributs plus surprenants de la plateforme Silverlight. Dans lexemple qui suit, le mme ImageBrush est utilis sur lattribut Foreground dune TextBox :
Exemple dImageBrush sur lattribut Foreground
<UserControl x:Class="LearnXaml.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:LearnXaml" Width="400" Height="100"> <Grid x:Name="LayoutRoot" Background="Black"> <TextBlock Text="WIPUS" FontSize="100" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock.Foreground> <ImageBrush ImageSource="wipuslogo.jpg" Stretch="UniformToFill"/> </TextBlock.Foreground>
78
</TextBlock> </Grid> </UserControl> c Fig. 1.50 : Exemple dImageBrush sur lattribut Foreground
79
Le langage XAML
Width="40" Canvas.Top="80" Canvas.Left="0" RadiusX="10" RadiusY="10"/> </Canvas> <Grid.Resources> <Storyboard x:Name="MagnifyStoryBoard" Duration="00:00:10" RepeatBehavior="Forever" AutoReverse="True"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="HeodeLabel" Storyboard.TargetProperty="FontSize" BeginTime="0" Duration="5"> <SplineDoubleKeyFrame KeyTime="00:00:00" Value="10"/> <SplineDoubleKeyFrame KeyTime="00:00:10" Value="100"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ProgressRect" Storyboard.TargetProperty="(Canvas.Left)"> <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <SplineDoubleKeyFrame KeyTime="00:00:10" Value="360"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </Grid.Resources> </Grid> </UserControl>
Cette animation est dclenche lors de lvnement MouseLeftButtonClic sur le TextBox HeodeLabel. Le code de la logique applicative de cette application appelle la mthode Begin du scnario MagnifyStoryBoard. Cette mthode va enclencher simultanment chacune des animations contenues dans ce scnario :
80
namespace LearnXaml { public partial class Page : UserControl { public Page() { InitializeComponent(); } private void HeodeLabel_Clic(object sender, MouseButtonEventArgs e) { MagnifyStoryBoard.Begin(); } } } c Fig. 1.51 : Animation non dmarre
81
Le langage XAML
Ce scnario a une dur (Duration), une rgle de rptition (RepeatBehavior) et une rgle de renversement (AutoReverse). La dure est le temps que prend un cycle complet de ce scnario ; il sagit dune valeur temporelle reprsente sous la forme hh:mm:ss. La rgle de rptition est elle aussi une valeur temporelle. Si cette rgle avait eu comme valeur 10:00:00, ce scnario se rpterait pendant une priode de 10 heures suivant lappel de la mthode Begin, et sarrterait ensuite. Dans le cas prsent, la valeur de la rgle de rptition est Forever ; cela signie que le scnario redmarrera ad vitam aeternam. La rgle de renversement, quant elle, est une valeur boolenne. Lorsquelle est vraie, une fois arrive sa n, le scnario sera rembobin. Une DoubleAnimationUsingKeyFrame est une animation modiant la valeur dun double (nombre rel) sur une certaine dure. Ses attributs StoryBoard.TagetName et StoryBoard.TargetProperty indiquent respectivement quel lment XAML contient ce double, et le nom de lattribut reprsentant ce double. Ces animations possdent un attribut BeginTime et une dure (Duration). Inutile de prciser que jouer avec ces StoryBoard est une bonne solution pour faire luire un bouton lorsque la souris passe par-dessus, et ainsi de suite.
82
Cette bannire affiche 3 publicits diffrentes ; des boutons sur le ct permettent de changer de publicit. Lorsque la souris passe par-dessus un de ces boutons, les publicits glissent les unes sur les autres jusqu ce que la publicit relative au bouton survol soit visible. Commenons par dnir linterface visuelle de la bannire sous la structure suivante :
j
Canvas
- StackPanel PubCanvas1 .Publicit1 (Image + Lien vers site web) .Bouton vers Publicit1 - StackPanel PubCanvas2 .Publicit2 (Image + Lien vers site web) .Bouton vers Publicit2 - StackPanel PubCanvas3 .Publicit3 (Image + Lien vers site web) .Bouton vers Publicit3
83
Le langage XAML
84
<Image Source="smallbtt.jpg"/> <TextBlock Text="Tell me more..." Foreground="Black" Margin="5" FontSize="14"/> </StackPanel> </HyperlinkButton> </Canvas> </Border> </StackPanel> <StackPanel Name="PubCanvas2" Orientation="Horizontal" Canvas.Left="80"> <Border Name="ToPub2" Background="Beige" BorderBrush="Black" BorderThickness="2" CornerRadius="3" Height="200" Width="80" MouseMove="ToPub2_MouseEnter" MouseEnter="ToPub2_MouseEnter"> <Canvas> <TextBlock Text="Heode" Canvas.Top="80" Canvas.Left="50" FontSize="16"> <TextBlock.RenderTransform> <RotateTransform Angle="90" CenterX="0" CenterY="0"/> </TextBlock.RenderTransform> </TextBlock> </Canvas> </Border> <Border Name="Publicit2" Background="White" Height="200" Width="260" Opacity="1"> <Canvas> <Image Source="heodelogo.jpg" Stretch="Uniform" Height="200" Width="160"/> <TextBlock Text="Heode" FontSize="35" Canvas.Top="100" FontFamily="Arial" Canvas.Left="100"/>
85
Le langage XAML
<HyperlinkButton NavigateUri="http:\\www.heode.com" Canvas.Left="110" Canvas.Top="130"> <StackPanel Orientation="Horizontal"> <Image Source="smallbtt.jpg"/> <TextBlock Text="Tell me more..." Foreground="Black" Margin="5" FontSize="14"/> </StackPanel> </HyperlinkButton> </Canvas> </Border> </StackPanel> <StackPanel Name="PubCanvas3" Orientation="Horizontal" Canvas.Left="160"> <Border Name="ToPub3" Background="Beige" BorderBrush="Black" BorderThickness="2" CornerRadius="3" Height="200" Width="80" MouseMove="ToPub3_MouseEnter" MouseEnter="ToPub3_MouseEnter" Opacity="1"> <Canvas> <TextBlock Text="Jubbeo" Canvas.Top="80" Canvas.Left="50" FontSize="16"> <TextBlock.RenderTransform> <RotateTransform Angle="90" CenterX="0" CenterY="0"/> </TextBlock.RenderTransform> </TextBlock> </Canvas> </Border> <Border Name="Publicit3" Background="White" Height="200" Width="260" Opacity="1"> <Canvas> <Image Source="jubbeologo.jpg" Stretch="Uniform" Height="200" Width="160"/>
86
<TextBlock Text="Jubbeo" FontSize="35" Canvas.Top="100" FontFamily="Arial" Canvas.Left="100"/> <HyperlinkButton NavigateUri="http:\\www.jubbeo.com" Canvas.Left="110" Canvas.Top="130"> <StackPanel Orientation="Horizontal"> <Image Source="smallbtt.jpg"/> <TextBlock Text="Tell me more..." Foreground="Black" Margin="5" FontSize="14"/> </StackPanel> </HyperlinkButton> </Canvas> </Border> </StackPanel> </Canvas> </UserControl> c Fig. 1.55 : Interface visuelle de la bannire
Leffet voulu est le suivant : chaque passage sur un des Border ToPub1, ToPub2 ou ToPub3, les publicits vont glisser vers la droite pour afficher la publicit relative au Border survol. Si la publicit relative au Border a dj gliss pralablement vers la droite, elle va glisser vers la gauche. Il y a donc 3 tats notre bannire :
Publicit3Visible (tat actuel de la bannire) ; Publicit2Visible ; j Publicit1Visible.
j j
87
Le langage XAML
Pour des raisons de lisibilit du code, crons une numration reprsentant ces tats :
Etat de la bannire (C#)
using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
Ce sont des animations qui vont nous permettre de passer dun tat lautre. Pour naviguer entre 3 tats, il faut 4 animations (ou scnario en loccurrence, chaque scnario contenant une unique animation). Ces animations sont :
DePub3Pub2 ; j DePub2Pub1 ; j DePub1Pub2 ; j DePub2Pub3.
j
88
<Canvas x:Name="LayoutRoot" Background="White"> <!--( dfinition de linterface ...)--> <Canvas.Resources> <Storyboard x:Name="DePub3Pub2"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PubCanvas3" Storyboard.TargetProperty="(Canvas.Left)"> <SplineDoubleKeyFrame KeyTime="00:00:00" Value="160"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="420"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Name="DePub2Pub1"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PubCanvas2" Storyboard.TargetProperty="(Canvas.Left)"> <SplineDoubleKeyFrame KeyTime="00:00:00" Value="80"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="340"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Name="DePub1Pub2"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PubCanvas2" Storyboard.TargetProperty="(Canvas.Left)"> <SplineDoubleKeyFrame KeyTime="00:00:00" Value="340"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="80"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Name="DePub2Pub3"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PubCanvas3" Storyboard.TargetProperty="(Canvas.Left)"> <SplineDoubleKeyFrame KeyTime="00:00:00" Value="420"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="160"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </Canvas.Resources>
89
Le langage XAML
</Canvas> </UserControl>
Cest ensuite sur les vnements MouseMouve et MouseEnter de chaque Border ToPub quil faut ajouter le dclenchement dun de ces scnarios. Une analyse pralable de la logique applicative semble requise :
Analyse de la logique applicative de la bannire
Dclarer un tat assign Publicit1Visible au dmarage de lapplication Dclarer un boolen signalant si une animation est dj en cours ou non pour viter que 2 animations ne dmarrent en mme temps { Ajouter chaque fin danimation un vnement modifiant ce boolen Modifier ce boolen avant chaque appel de la mthode Begin dun animation } Dclarer une destination de type EtatBannire. Cette destination est la dernire publicit survole par la souris de lutilisateur. Crer une mthode StartNextAnimation qui dmare une animation en fonction des valeurs tat et destination. Appeler cette mthode chaque fin danimation au cas o ltat soit actuel diffrent de la destination actuelle Lors du survol des Borders ToPub. { Assigner la publicit courante comme destination Si aucune animation nest en cours, alors appeler la mthode StartNextAnimation }
90
namespace SilverlightBanner { public partial class Page : UserControl { private EtatBannire tat = EtatBannire.Publicit3Visible; private bool AnimationEnCours = false; private EtatBannire destination = EtatBannire.Publicit3Visible; public Page() { InitializeComponent(); DePub1Pub2.Completed DePub2Pub1.Completed DePub2Pub3.Completed DePub3Pub2.Completed } void SetEtatToPub1(object sender, EventArgs e) { tat = EtatBannire.Publicit1Visible; AnimationEnCours = false; StartNextAnimation(); } void SetEtatToPub2(object sender, EventArgs e) { tat = EtatBannire.Publicit2Visible; AnimationEnCours = false; StartNextAnimation(); += += += += new new new new EventHandler(SetEtatToPub2); EventHandler(SetEtatToPub1); EventHandler(SetEtatToPub3); EventHandler(SetEtatToPub2);
91
Le langage XAML
} void SetEtatToPub3(object sender, EventArgs e) { tat = EtatBannire.Publicit3Visible; AnimationEnCours = false; StartNextAnimation(); } private void ToPub3_MouseEnter(object sender, MouseEventArgs e) { destination = EtatBannire.Publicit3Visible; if (AnimationEnCours == true) return; StartNextAnimation(); } private void ToPub2_MouseEnter(object sender, MouseEventArgs e) { destination = EtatBannire.Publicit2Visible; if (AnimationEnCours == true) return; StartNextAnimation(); } private void ToPub1_MouseEnter(object sender, MouseEventArgs e) { destination = EtatBannire.Publicit1Visible; if (AnimationEnCours == true) return; StartNextAnimation(); } private void StartNextAnimation() { if (tat == destination) return; AnimationEnCours = true; switch (tat)
92
{ case EtatBannire.Publicit1Visible: DePub1Pub2.Begin(); break; case EtatBannire.Publicit2Visible: if (destination == EtatBannire.Publicit1Visible) DePub2Pub1.Begin(); else DePub2Pub3.Begin(); break; case EtatBannire.Publicit3Visible: DePub3Pub2.Begin(); break; } } } }
La bannire devrait maintenant fonctionner merveille ; cependant, ce nest pas le cas. Lors de lexcution du premier scnario, la publicit 3 sort du contrle Silverlight et empite sur la page ASP.NET (ou HTML) le contenant.
Ce problme nest pas un problme d au code Silverlight mais bien un problme d au code ASP.NET (ou HTML) gnr par VisualStudio. Dans la page ASP.NET hte du projet de dveloppement Silverlight, remplacez la taille du contrle Silverlight par With =500 et Height=200 :
93
Le langage XAML
94
Check-List
1.11 Check-List
Ce chapitre vous a fourni les bases ncessaires la comprhension dun chier XAML. Nous avons tudi ici les diffrents contrles et fonctionnalits de base dune interface Silverlight :
a le langage XAML driv du XML ; a les diffrents contrles de Layout structurants une interface ; a quelques contrles daffichages dinformations ; a quelques contrles de captures dinformations ; a les bases du Binding ; a quelques lments de design.
Enn, nous avons conclu par la cration complte dune bannire Silverlight.
95
2
2.1 Introduction Expression Studio ...................... 2.2 Expression Design ...................................... 2.3 Expression Encoder 2 .................................. 2.4 Expression Blend 2 ..................................... 2.5 Intraction entre Expression Blend et Visual Studio 2008 .................................................... 2.6 Check-List ................................................ 98 99 102 104 109 111
98
Expression Design
Les plus utiles, dans le cas de Silverlight, sont Expression Blend, Expression Media et Encoder (les deux derniers sont fortement lis). Si vous ne comptez pas tirer parti de la puissance de Silverlight pour la vido, Expression Blend vous suffira. Expression Studio est payant mais vous disposez dune version dvaluation vous permettant de tester le produit. Vous pourrez trouver ce produit en magasin, la FNAC par exemple ou chez des partenaires Microsoft.
Un bon exemple dapplication ralis en XAML
Un bon exemple dapplication ralise en XAML est Expression Studio. En effet, lensemble des outils de la gamme Expression a t ralis en XAML.
Partons maintenant la dcouverte de ces 5 outils qui vous serviront tout au long de la cration dune application web Silverlight.
99
Si vous voulez crer le mme dessin en XAML, voici quoi cela ressemblera :
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Layer_1_0" Width="800" Height="600" Canvas.Left="0" Canvas.Top="0"> <Rectangle Width="345.983" Height="155.492" Canvas.Left="253.257" Canvas.Top="170.506" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000"> <Rectangle.Fill> <LinearGradientBrush StartPoint="-0.00144939,0.5" EndPoint="1.00145,0.5"> <LinearGradientBrush.GradientStops> <GradientStop Color="#FF000000" Offset="0.237443"/>
100
Expression Design
<GradientStop Color="#FFF3F025" Offset="0.502283"/> <GradientStop Color="#FFE9F100" Offset="0.589041"/> <GradientStop Color="#FFED2E16" Offset="0.776256"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <Ellipse Width="77.4962" Height="78.9961" Canvas.Left="554.742" Canvas.Top="122.509" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000"> <Ellipse.Fill> <LinearGradientBrush StartPoint="-0.00653628,0.5" EndPoint="1.00654,0.5"> <LinearGradientBrush.GradientStops> <GradientStop Color="#FF000000" Offset="0.237443"/> <GradientStop Color="#FFF3F025" Offset="0.502283"/> <GradientStop Color="#FFE9F100" Offset="0.589041"/> <GradientStop Color="#FFED2E16" Offset="0.776256"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> </Canvas>
Imaginez alors combien de temps cela vous prendrait de crer des dessins beaucoup plus complexes ? Expression Design est donc un outil indispensable la ralisation dinterfaces riches. Expression Design fait lobjet de livres entiers. Si vous tes habitu Photoshop, vous naurez aucun problme le prendre en main.
XAML vs Images
Si XAML reprsente une image, pourquoi ne pas directement prendre cette image et lajouter comme ressource notre projet en utilisant la balise XAML Image ? Tout dpend du type dapplications que vous voulez raliser. Si limage fait partie intgrante de votre interface et que celle-ci soit extensible, vous devez la prvoir en XAML. Mais si vous devez afficher une srie darticles avec des images, il est inutile de transformer ces images en XAML.
101
Une fois la vido importe, vous pouvez la visualiser laide du lecteur intgr au programme. Vous avez la possibilit de couper la vido comme vous le dsirez pour y placer des chapitres ou des explications. Lorsque votre dition est termine, vous pouvez regarder toute une srie de paramtres droite. Dans le dernier onglet, output, vous avez la possibilit de choisir un lecteur pour votre vido. Il en existe toute une srie et vous pouvez en crer vous-mme de nouveaux ou diter les existants en les ouvrant dans Expression Blend laide du petit carr situ juste ct de la liste droulante. Lorsque vous avez termin, cliquez sur Encode et attendez le rsultat qui devrait safficher dans une nouvelle fentre Internet explorer.
102
Expression Encoder 2
Vous pourrez trouver tous les chiers JavaScript en rapport dans le mme dossier que le chier Default.html. Microsoft Expression Encoder permet galement de senregistrer (voix et son) an de crer vos propres vidos lmes par webcam ou camscope. Pour cela, cliquez sur longlet Live Encoding. Une nouvelle fentre apparat en overlay. Vous devez choisir la source de la vido et la source audio et cliquez sur Start. Une fois lenregistrement effectu, vous obtenez un aperu en vous rendant dans longlet output et en cliquant sur Launch Preview.
103
Aprs avoir install le SP1, vous pouvez crer un projet Silverlight 2 en lui donnant un nom et en cliquant sur OK. Un projet vide sest cr. Vous pouvez basculer entre laffiche design ou XAML par les onglets verticaux de droite. Mme un projet blanc nest pas tout fait vide puisque Blend vous prpare directement un conteneur de base (Grid) :
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SilverlightApplication2.Page" Width="640" Height="480"> <Grid x:Name="LayoutRoot" Background="White"/> </UserControl>
104
Expression Blend 2
Si on passe nouveau du ct Design et que lon ajoute un rectangle, on remarquera que le code XAML sest directement mis jour :
c Fig. 2.4 : Expression Blend 2 <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SilverlightApplication2.Page" Width="640" Height="480"> <Grid x:Name="LayoutRoot" Background="White"> <Rectangle Height="73" Margin="117,122,280,0" VerticalAlignment="Top" Stroke="#FF000000"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF000000"/> <GradientStop Color="#FF0F2B66" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> </UserControl>
Au niveau des proprits des lments, on retrouve assez facilement des lments dj vus dans Microsoft Expression Design 2. Vous pouvez consulter tout les lments XAML disponibles en cliquant sur la double che gauche. Par dfaut, ils ne sont pas tous affichs. Si vous voulez les afficher tous, vous devrez cocher la case en haut droite Show all.
105
Llment le plus important de Blend est la colonne Objects and Timeline. Elle vous permet de visualiser les lments que vous avez ajouts votre projet et surtout de voir leur situation dans le projet. En effet, cette colonne reprsente les lments sous forme darbre de telle manire que vous puissiez voir comment les lments sont imbriqus les uns dans les autres.
Les noms
Il est trs important de donner des noms vos lments. Cest ainsi que vous pouvez les retrouver quand vous en avez beaucoup sur une mme interface. De la mme manire, lorsque vous voudrez interagir avec ceux-ci par code, vous devrez connatre leur nom dans le code. Sils nont pas de noms, on peut considrer les lments comme inaccessibles.
106
Expression Blend 2
Cest aussi dans cette colonne que vous allez contrler les diffrentes animations de votre application. Ainsi, pour animer votre rectangle, il faut cliquer sur le petit bouton en forme de plus et donner un nom votre animation. Vous entrez alors en mode denregistrement. Vous avez une ligne du temps gauche et un encadr rouge droite qui montre la zone denregistrement. Effectuer une animation avec Blend et Silverlight savre trs simple, surtout si vous tes habitu jouer avec les mmes concepts pour Flash/Flex. Tout se fait par point darrt. Un point darrt est x ds que vous dplacez un lment. Pour crer une animation, placez-vous sur la ligne du temps et dplacez llment. Pour visualiser lanimation, cliquez sur le bouton Play.
107
Storyboard.TargetProperty="(UIElement.RenderTransform). (TransformGroup.Children)[3].(TranslateTransform.Y)"> <SplineDoubleKeyFrame KeyTime="00:00:01" Value="63"/> <SplineDoubleKeyFrame KeyTime="00:00:02" Value="-74"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(UIElement.RenderTransform). (TransformGroup.Children)[3].(TranslateTransform.X)"> <SplineDoubleKeyFrame KeyTime="00:00:01" Value="125"/> <SplineDoubleKeyFrame KeyTime="00:00:02" Value="244"/> </DoubleAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush. GradientStops)[1].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="00:00:01" Value="#FF0F2B66"/> <SplineColorKeyFrame KeyTime="00:00:02" Value="#FFA9BCE4"/> </ColorAnimationUsingKeyFrames> </Storyboard> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Rectangle Height="73" Margin="117,122,280,0" VerticalAlignment="Top" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" x:Name="rectangle"> <Rectangle.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </Rectangle.RenderTransform> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF000000"/> <GradientStop Color="#FF0F2B66" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> </UserControl>
108
la simple vue de ce code, vous vous rendez compte quel point Expression Blend peut tre utile.
La limite dExpression Blend
Si les outils pouvaient gnrer le code sans faire derreurs, nous naurions plus besoin dexperts. Trs souvent, une intervention humaine est apprcie pour optimiser le code. Tout ceci sera expliqu dans les concepts avancs. Retenez que Blend ne remplace pas un code bien crit la main. Il est l pour vous simplier la vie mais tentez de toujours comprendre ce quil fait.
109
Considrez toujours Visual Studio comme votre outil principal et Expression Blend comme un outil de retouche plutt quun outil de cration dapplication Silverlight. Expression Blend ne permet pas de modier les chiers contenant la logique mtier. Si vous cliquez sur la petite croix devant le nom du chier, vous verrez un sous-chier ; cest le chier contenant tout ce qui est dynamique dans lapplication. Seul Visual Studio ou votre Bloc-notes vous permet de modier ces chiers :
using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace SilverlightApplication1 { public partial class Page : UserControl { public Page() { InitializeComponent(); } } }
Si vous travaillez deux sur un mme projet, il arrive frquemment quune personne travaille sur le chier xaml et lautre sur le chier cs. Attention toutefois aux abus ; la plupart du temps, pour avoir un code cohrent, il faut une interface dj bien dnie ; le chier xaml est souvent plus avanc que le chier cs qui lui est ddi. Vous aurez peu loccasion dutiliser Expression Web et Expression Media qui ne seront pas dcrits dans ce livre. Nous pouvons donc terminer ce chapitre parenthse pour partir la conqute des donnes.
110
Check-List
2.6 Check-List
Dans ce chapitre nous avons explor la gamme Expression avec :
a Expression Design ; a Expression Blend ; a Expression Encoder ; a Linteraction entre Visual Studio et Expression Blend.
111
3
3.1 Utilisez SQL et votre base de donnes ............... 3.2 Exploitez vos donnes sur Oracle .................... 3.3 MySQL et Silverlight .................................... 3.4 LINQ ..................................................... 3.5 Les Web services ....................................... 3.6 ADO.NET/Silverlight ................................... 3.7 Crez un widget mto ................................ 3.8 Traitez un ux de donnes RSS ........................ 3.9 Check-list ................................................. 114 120 124 126 134 143 153 174 179
une chane de connexions permettant de vous authentier et de cibler la base de donnes attaquer ; une connexion qui souvre grce aux paramtres placs dans la chane de connexion ; une commande qui est une chane de caractres reprsentant une requte SQL ; un objet pour rcuprer les rsultats an de pouvoir les afficher.
Une fois que nous avons tous ces lments, nous pouvons commencer. Tout dabord, la chane de connexion. Cest un concept qui reviendra pour les autres SGBD galement. Pour SQL Serveur, elle ressemble ceci :
Data Source=PC-MACWIN\SQLEXPRESS;Initial Catalog=WipusBD;Persist Security Info=True;User ID=WipusDBManager; Password=WipusManager
114
Cette chane de connexion, nous devons la sauvgarder dans une variable de type string. Ce type de variable est spcialement prvu pour accepter les chanes de caractres :
string connectionString = @"Data Source=PC-MACWIN\SQLEXPRESS;Initial Catalog=WipusBD;Persist Security Info=True;User ID=WipusDBManager; Password=WipusManager";
Une fois cette chane sauvegarde, nous pouvons lutiliser pour initialiser une connexion. Cela se fait laide de lobjet SqlConnection :
SqlConnection myConnection; myConnection = new SqlConnection(connectionString);
Le try/catch permet de dtecter sil y a eu une erreur lors de la connexion la base de donne. Si cest le cas, vous pourrez la grer dans le catch. Autrement, le code continuera sexcuter sans passer dans le catch. Avant daller plus loin, nous allons procder un rappel concernant SQL.
SQL
Structured Query Language est un langage qui vous permet daccder aux donnes situes dans une base de donnes. Cest un langage uniformis qui doit, normalement, fonctionner sur tous les SGBD. Cependant, vous trouverez quelques nuances quand vous utiliserez SQL Server ou Oracle, ces deux SGBD tant si puissants quils ont ajout un lot de nouvelles fonctionnalits au SQL. Sans rentrer dans les dtails, SQL permet de raliser 4 actions basiques : j slectionner ; j supprimer ; j diter ; j ajouter.
115
Chaque action que peut effectuer SQL a son mot-cl. Ainsi, pour la slection, on a le mot-cl SELECT, pour la suppression, le mot-cl est DELETE, pour diter UPDATE et INSERT pour lajout dans une base de donnes. Pour la slection, outre le mot-cl SELECT, nous devons signier ce que nous souhaitons slectionner (la projection) et le critre de slection sur cette slection. Par exemple : Rechercher le nom, le prnom et lge des tudiants de deuxime anne. Nous avons ici une projection : nom, prnom et ge, ainsi quune slection, cest--dire le fait de slectionner uniquement les lves de deuxime anne. Pour la projection, nous avons presque tous les lments pour notre requte :
SELECT nom, prenom, age FROM etudiants
Dans cet exemple, nous ne prenons en compte une seule table. Il arrive frquemment de devoir aller rechercher une information situe dans plusieurs tables. Imaginez que notre base de donnes stocke le cours auquel ltudiant participe actuellement. Pour cela, il y aurait une autre table cours avec une rfrence vers la table des tudiants. Si vous voulez la liste des tudiants se trouvant au cours de maths, nous allons obtenir :
SELECT etudiants.nom, etudiants.prenom, etudiants.age FROM etudiants, cours WHERE etudiants.Id = cours.Id AND cours.Nom = Math
Cette faon ne reprsente quune manire de chercher le rsultat. Nous pourrions utiliser dautres mthodes avec les mots-cls INNER JOIN ou JOIN. Pour ce qui est de linsertion de nouveaux lments ainsi que de la suppression et modication, vous dcouvrirez, au long du chapitre, la syntaxe fort proche de la slection.
116
SqlCommand cmd = new SqlCommand("SELECT nom, prenom, age " + "FROM etudiants " + "WHERE annee = 2 " + "AND age < 22 ", con);
Lobjet SqlCommand prend en paramtre une chane de caractres reprsentant la requte SQL ainsi que lobjet connexion que nous avons initialis auparavant (SqlConnection). Il peut arriver que la requte ait des donnes dites dynamiques. Imaginez par exemple que dans votre Silverlight, vous ayez un moment donn demander lge maximal des lves que vous voudriez afficher. Cette donne aura t sauve dans une variable de type int ou short vu que lge dune personne dpasse rarement les 100 ans. Vous pouvez exploiter ces donnes au sein de votre requte :
SqlCommand cmd = new SqlCommand("SELECT nom, prenom, age " + "FROM etudiants " + "WHERE annee = " + "AND age < " + VOTRE VARIABLE ICI, myConnection);
SqlParameter est un objet qui dnit un paramtre de votre requte. Le paramtre est
117
Ainsi, les attaques SQL ne sont pas possibles. Comme on connat le type quon doit obtenir, on rduit dj le champ de lattaque. De plus, il traite automatiquement les caractres tels que "". Pour excuter notre requte, nous devons crer un reader. Cet objet va nous permettre de lire les rsultats de la requte pour les afficher ensuite :
private static void ReadOrderData(string connectionString) { string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;"; using (SqlConnection connection = new SqlConnection( connectionString)) { SqlCommand command = new SqlCommand( queryString, connection); connection.Open(); SqlDataReader reader = command.ExecuteReader(); try { while (reader.Read()) { Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1])); } } finally { // Always call Close when done reading. reader.Close(); } } }
Exemple
Cet exemple provient dune application console. tant donn que vous navez pas encore les notions suffisantes pour ASP.NET, nous avons volontairement limit lexemple. Rendez-vous au chapitre 5, Silverlight et ASP.NET, pour voir comment traiter les donnes correctement. Plus loin dans ce chapitre, nous dcouvrirons galement comment fonctionne laccs direct une base de donnes via Silverlight.
118
Les mthodes montres jusquici ne sont applicables quau travers dun Web service. Nous verrons les Web services plus loin dans ce chapitre. Nanmoins, il est rare quun Web service expose une mthode qui renvoie un DataReader. Vous pouvez utiliser la fonction suivante :
/// <summary> /// Converts a SqlDataReader to a DataSet /// <param name=reader> /// SqlDataReader to convert.</param> /// <returns> /// DataSet filled with the contents of the reader.</returns> /// </summary> public static DataSet convertDataReaderToDataSet(SqlDataReader reader) { DataSet dataSet = new DataSet(); do { // Create new data table DataTable schemaTable = reader.GetSchemaTable(); DataTable dataTable = new DataTable(); if (schemaTable != null) { // A query returning records was executed for (int i = 0; i < schemaTable.Rows.Count; i++) { DataRow dataRow = schemaTable.Rows[i]; // Create a column name that is unique // in the data table string columnName = (string)dataRow["ColumnName"]; //+ "<C" + i + "/>"; // Add the column definition to the data table DataColumn column = new DataColumn(columnName, (Type)dataRow["DataType"]); dataTable.Columns.Add(column); } dataSet.Tables.Add(dataTable); // Fill the data table we just created while (reader.Read()) { DataRow dataRow = dataTable.NewRow();
119
for (int i = 0; i < reader.FieldCount; i++) dataRow[i] = reader.GetValue(i); dataTable.Rows.Add(dataRow); } } else { // No records were returned DataColumn column = new DataColumn("RowsAffected"); dataTable.Columns.Add(column); dataSet.Tables.Add(dataTable); DataRow dataRow = dataTable.NewRow(); dataRow[0] = reader.RecordsAffected; dataTable.Rows.Add(dataRow); } } while (reader.NextResult()); return dataSet; }
120
Vous pouvez ensuite vous connecter la base de donnes Oracle via sa chane de connexion qui doit ressembler ceci :
OraDb= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)) ) (CONNECT_DATA= (SERVER=DEDICATED) (SERVICE_NAME=ORCL) ) )
Il faut donc placer cette chane de connexion dans une variable an de pouvoir lutiliser plus tard dans le programme :
string oradb = "Data Source=(DESCRIPTION=" + "(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=ORASRVR)(PORT=1521)))" + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)));" + "User Id=scott;Password=tiger;";
Une fois la chane sauve, vous pouvez crer une connexion partir de cette chane de la manire suivante :
OracleConnection conn = new OracleConnection(oradb);
Ou si vous prfrez :
OracleConnection conn = new OracleConnection(); conn.ConnectionString = oradb;
La suite est pratiquement la mme que ce que vous connaissez avec SQL Serveur. Vous devez crer une commande :
string sql = "select dname from dept where deptno = 10"; // C# OracleCommand cmd = new OracleCommand(sql, conn); cmd.CommandType = CommandType.Text;
121
Et terminer la connexion proprement, comme nous laurions fait avec SQL Serveur :
conn.Close(); conn.Dispose();
Voici une meilleure faon de faire lorsquon voit le code dans son ensemble :
using (OracleConnection conn = new OracleConnection(oradb)) { conn.Open(); OracleCommand cmd = new OracleCommand(); cmd.Connection = conn; cmd.CommandText = "select dname from dept where deptno = 10"; cmd.CommandType = CommandType.Text; OracleDataReader dr = cmd.ExecuteReader(); dr.Read(); label1.Text = dr.GetString(0); }
Gestion derreur
Lorsque vous programmez, noubliez jamais de traiter correctement les erreurs, notamment louverture dune connexion.
122
Le provider Oracle fournit une srie derreurs que vous pouvez interprter laide de lobjet OracleException :
catch (OracleException ex) // catches only Oracle errors { switch (ex.Number) { case 1: MessageBox.Show("Corruption clef primaire"); break; case 12545: MessageBox.Show("La base de donnes ne rpond pas."); break; default: MessageBox.Show("Autre erreur: " + ex.Message.ToString()); break; } } catch (Exception ex) // catches any error
123
{ MessageBox.Show(ex.Message.ToString()); }
Si vous effectuez une requte qui rapatrie plusieurs lments, utilisez la mthode Read du DataReader :
while (dr.Read()) // C# { listBox1.Items.Add("The " + dr["dname"].ToString() + " department is in " + dr["loc"].ToString()); }
Voil notre introduction laccs aux donnes via Oracle termine. Il y a bien entendu beaucoup plus de choses faire avec cette DLL mais ce nest pas lobjectif de notre livre. Reportez-vous lannexe 3, Webographie, pour obtenir les liens qui vous guideront vers de linformation sur le sujet.
124
MySQL et Silverlight
La chane de connexion est plus petite que pour Oracle et SQL Serveur. Cest quasiment la seule chose qui changera dans notre code. Aprs avoir enregistr cette chane de connexion, nous pouvons louvrir :
try { conn = new MySqlConnection( connStr ); conn.Open(); GetDatabases(); } catch (MySqlException ex) { MessageBox.Show( "Error connecting to the server: " + ex.Message ); }
Nous avons vu ici comment changer la base de donnes concerne par la requte, ce qui ne peut pas se faire dans les autres providers. Vous devrez, chaque fois, utiliser une chane de connexion diffrente pour chaque base de donnes.
125
Cest peu prs tout ce que vous devez connatre sur les connexions un serveur MySQL.
3.4 LINQ
LINQ est apparu avec le Framework 3.0 de la plateforme .NET. Il a vite t apprci par les dveloppeurs pour la facilit quil apporte et sa merveilleuse intgration dans Visual Studio 2008. LINQ a su plaire aux dveloppeurs qui avaient lhabitude daller rechercher leurs donnes dans des bases de donnes : SQL Serveur dans un premier temps. Il existe maintenant profusion de providers qui permettent de connecter dautres SGBD. En effet, mme si le SQL est un langage de choix, il nexiste pas de compilateur qui sache reprer une erreur dans notre syntaxe SQL. Il nexiste pas non plus dIntelliSense pour SQL. Ce nest videmment pas la seule raison de ce succs. LINQ est trs facile prendre en main. En effet, sa syntaxe est simple et ressemble beaucoup au SQL. Voyez par vous-mme lexemple dun projet LINQ to Object :
using using using using System; System.Collections.Generic; System.Linq; System.Text;
namespace LINQ { class Program { static void Main(string[] args) { string[] names = { "Burke", "Connor", "Frank", "Everett", "Albert", "George", "Harris", "David" };
126
LINQ
IEnumerable<string> query = from s in names where s.Length == 5 orderby s select s.ToUpper(); foreach (string item in query) Console.WriteLine(item); Console.ReadLine(); } } }
Nous retrouvons les diffrents lments qui constituent une requte SQL :
j j j
Il existe de nombreux projets LINQ. La communaut .NET sest empare du projet pour ltendre dautres sources de donnes. Voici un tableau rcapitulatif et non exhaustif des diffrents projets LINQ :
Tableau 3.1 : Liste des providers LINQ Provider LINQ to Object LINQ to SQL LINQ to XML LINQ to DataSet LINQ to Entities LINQ to Amazon LINQ to Active Directory LINQ to Bindable Sources LINQ over C# LINQ to CRM Description Permet dutiliser LINQ sur des collections dobjets. Permet dutiliser LINQ avec une source de donnes relationnelles (SQL Serveur pour le moment). Utilis pour manipuler des sources XML Un provider pour utiliser LINQ avec des DataSets LINQ sappuyant sur un modle dentit Providers pour attaquer les donnes dAmazon Providers pour contacter Active Directory Permet de facilement la gestion des tats dune application. Permet de passer du C# laide de LINQ. Providers pour CRM
127
Tableau 3.1 : Liste des providers LINQ LINQ to Geo LINQ to Excel LINQ to Expressions LINQ to FlickR LINQ to Google LINQ to Indexes LINQ to JSON LINQ to NHibernate LINQ to JavaScript LINQ to LDAP LINQ to LLBLGen Pro LINQ to Lucene LINQ to Metaweb LINQ to MySQL, Oracle et PostGreSql LINQ to NCover LINQ to Opf3 LINQ to Parallel LINQ to RDF File LINQ to SharePoint LINQ to SimpleDB LINQ to Streams LINQ to WebQueries LINQ to WMI LINQ to XtraGrid LINQ pour manipuler des donnes go spatiales LINQ pour manipuler des tableaux Excel Permet de manipuler des arbres en utilisant LINQ. Permet daller rechercher des informations sur un compte FlickR. LINQ pour requter Google Permet dajouter la notion dindex LINQ. Pour manipuler JSON laide de LINQ Permet de faire le pont entre LINQ et NHibernate. Permet dutiliser LINQ dans du JavaScript. Permet de manipuler un annuaire LDAP avec LINQ. Permet dtendre LINQ to SQL (prise en charge de plus de fonctionnalits venant de SQL). LINQ pour la manipulation de chanes de caractres LINQ pour Freebase LINQ pour Oracle, MySQL et PostGreSql (implmentation de LINQ to SQL 2) LINQ pour NCover LINQ pour le Framework Opf3 Aussi appel PLINQ, permet de programmer en multi core avec LINQ. Comme son nom lindique, permet de manipuler des chiers RDF laide de LINQ. Permet de manipuler les listes SharePoint avec LINQ. LINQ to SQL pour Amazon SimpleDB Manipulation de donnes de streaming avec LINQ Permet de traiter le Web comme une base de donnes. LINQ pour WMI LINQ pour manipuler les grids
128
LINQ
Le tableau parle de lui-mme, il existe ce jour normment de providers pour LINQ. Nous nallons pas les dtailler tous dans ce livre.
La premire chose qui choque, lorsque nous rencontrons une requte LINQ, ce sont les nouveaux mot-cls :
from ; where ; j orderby ; j select, etc.
j j
Ces mots-cls ont t introduits dans le Framework 3.0. Lorsque le compilateur tombe sur ces mots-cls, il transforme tout en succession de mthodes :
IEnumerable<string> query = names .Where(s => s.Length == 5) .OrderBy(s => s) .Select(s => s.ToUpper());
Nous nallons pas nous terniser sur le sujet tant il est vaste. Nous verrons juste un exemple dutilisation de LINQ to XML qui nous permettra de manipuler du XAML.
129
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300" Loaded="UserControl_Loaded"> <Grid x:Name="LayoutRoot" Background="White"> <StackPanel VerticalAlignment="Top" x:Name="stkMenu" Orientation="Horizontal"></StackPanel> </Grid> </UserControl>
Dans le code attach notre chier XAML, nous allons instancier un objet qui se connectera au Web service que nous verrons plus tard :
using using using using System; System.Windows; System.Windows.Controls; System.Xml.Linq;
namespace HDI_Silverlight_LinqandXaml_sl_cs { public partial class Page : UserControl { public Page() { InitializeComponent(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { MenuServiceReference.MenuServiceClient msc = new MenuServiceReference.MenuServiceClient(); msc.GetMenuItemsCompleted += new EventHandler<MenuServiceReference.GetMenuItems CompletedEventArgs> (msc_GetMenuItemsCompleted); msc.GetMenuItemsAsync(); } void msc_GetMenuItemsCompleted(object sender, MenuServiceReference.GetMenuItemsCompletedEventArgs e) { foreach (XElement xe in e.Result) { stkMenu.Children.Add(System.Windows.Markup.XamlReader.Load (xe.ToString()) as UIElement); } }
130
LINQ
} }
Toujours le mme fonctionnement. On va rechercher le contenu et on appelle une mthode une fois le contenu tlcharg. Si on regarde au niveau de notre Web service, nous avons une interface :
using System.Collections.Generic; using System.ServiceModel; using System.Xml.Linq; namespace HDI_Silverlight_LinqandXaml_web_cs { [ServiceContract] public interface IMenuService { [OperationContract] List<XElement> GetMenuItems(); } }
Cette interface ne dnit quune mthode. Cette mthode est complte dans la classe qui implmente linterface :
using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace HDI_Silverlight_LinqandXaml_web_cs { public class MenuService : IMenuService { public List<XElement> GetMenuItems() { List<XElement> menuelementlist = new List<XElement>(); XNamespace xmlns = "http://schemas.microsoft.com/client/2007"; var elements = from x in DataBaseClass.GetDataElements() select new XElement(xmlns + x.ElementType, new XAttribute("Width", x.Width), new XAttribute("Height", x.Height), new XAttribute("Content", x.Content));
131
Cest dans ce chier que lon voit lutilisation de LINQ to XML. LINQ va rechercher les donnes dans une classe DataBaseClass :
using using using using System; System.Collections.Generic; System.Linq; System.Web;
namespace HDI_Silverlight_LinqandXaml_web_cs { public static class DataBaseClass { public static List<DataElement> GetDataElements() { List<DataElement> lst = new List<DataElement>(); lst.Add(new DataElement { ElementType = "Button", Width = "100", Height = "50", Content = "Menu Item 1" }); lst.Add(new DataElement { ElementType = "Button", Width = "150", Height = "50", Content = "Menu Item 2" }); lst.Add(new DataElement { ElementType = "Button", Width = "100", Height = "50", Content = "Menu Item 3" }); return lst; } } public class DataElement { public string ElementType { get; set; } public string Width { get; set; } public string Height { get; set; } public string Content { get; set; } } }
132
LINQ
Cette classe fait office de base de donnes. On aurait pu imaginer aller rechercher lobjet dans une base de donnes. Une fois le Web service termin, nous devons ajouter une rfrence dans notre projet Silverlight, ce qui cre un chier ServiceReference.cong :
<configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IMenuService" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:7107/MenuService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMenuService" contract="MenuServiceReference.IMenuService" name="BasicHttpBinding_IMenuService" /> </client> </system.serviceModel> </configuration>
Lexemple est termin. Il vous reste dclarer un tag Silverlight dans une page pour tester votre code :
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;"> <head runat="server"> <title>HDI-Silverlight-LinqandXaml-sl-cs</title> </head> <body style="height:100%;margin:0;"> <form id="form1" runat="server" style="height:100%;"> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
133
<div style="height:100%;"> <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/HDI-Silverlight-LinqandXaml-sl-cs.xap" MinimumVersion="2.0.31005.0" Width="100%" Height="100%" /> </div> </form> </body> </html>
Nous pouvons maintenant passer la partie Web service qui vous permettra de mieux comprendre comment les exemples prcdents fonctionnent. LINQ est trs complexe et le Framework a du connatre beaucoup de modication et dajout pour permettre lutilisation de LINQ. Reportez-vous lannexe 3, Webographie, si vous souhaitez plus dinformation sur lutilisation de LINQ. Aujourdhui, le provider LINQ le plus utilis est LINQ to Entities. Il vous permet de vous connecter votre base de donnes et traiter les donnes de celle-ci comme si sagissait dobjets que vous avez lhabitude de manipuler dans vos programmes.
134
Le Framework .NET propose plusieurs types de Web services. Pour comprendre, il faut un petit historique. En fait, avant larrive de Silverlight et du Framework 3.0, les Web services se craient avec ASP.NET sous forme de chier asmx. Depuis, Microsoft a introduit WCF (Windows Communication Foundation). Cette nouvelle brique du Framework permet de crer des Web services respectant des normes qui ne sont plus seulement les normes de Microsoft mais des normes appliques un peu partout sur le Web. Ce qui a pour but de crer un Web interoprable, cest--dire o la technologie utilise ninuence plus les donnes quelle peut manipuler. Ainsi, si WCF expose des donnes, du code PHP sera capable daller rechercher linformation, etc. De la mme manire, du code .NET pourra rcuprer de linformation en provenance de PHP ou Ruby. Cest ce qui se passe lorsque vous contactez lAPI Twitter puisque Twitter et son API sont dvelopps en Ruby et pourtant, .NET sait facilement lire les donnes exposes sur lAPI. Dans lexemple qui va nous servir dapprentissage, nous allons crer deux Web services diffrents. Un en ASP.NET, mme si vous navez pas encore eu le temps de lire le chapitre dintroduction. Un autre, en WCF, qui exposera des donnes simples et complexes, que nous devrons exploiter dans notre application Silverlight. Vous devez donc crer une application Silverlight dans Visual Studio. Visual Studio vous demande ensuite si vous souhaitez attacher un projet ASP.NET votre projet Silverlight. Cest le cas ici. Dans ce projet ASP.NET, nous devons ajouter un chier ASMX (chier de Web service) :
135
Ce chier fait rfrence un autre chier situ dans App_Code. Si ce chier nexiste pas, crez-le. Ce chier dnira les diffrentes mthodes que notre Web service expose :
using using using using using using using System; System.Collections; System.Linq; System.Web; System.Web.Services; System.Web.Services.Protocols; System.Xml.Linq;
/// <summary> /// Summary description for SimpleAsmx /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding (ConformsTo = WsiProfiles.BasicProfile1_1)] // To allow this Web service to be called from script, // using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class SimpleAsmx : System.Web.Services.WebService { public SimpleAsmx() { //Uncomment the following line if using //designed components //InitializeComponent(); } [WebMethod] public string HelloWorld() {
136
return "Hello World"; } [WebMethod] public string SayHelloToMe(string name) { return string.Format("Hello {0}, how are you?", name); } }
Nous avons ici deux mthodes exposes. Pour exposer une mthode, il suffit de lui appliquer un attribut WebMethod. La premire fonction fait un clbre Hello World et la deuxime prend un paramtre et demande lutilisateur comment il va. Notre Web service ASP.NET est termin. Nous pouvons faire la mme chose pour WCF. De la mme manire, vous allez voir apparatre dans votre projet un nouveau chier dont lextension est svc :
<%@ ServiceHost Language="C#" Debug="true" Service="SimpleWCF" CodeBehind="~/App_Code/SimpleWCF.cs" %>
Ce chier fait rfrence un chier code dans App_Code comme pour le Web service ASP.NET :
using using using using using using System; System.Collections.Generic; System.Linq; System.Runtime.Serialization; System.ServiceModel; System.Text;
// NOTE: If you change the class name "SimpleWCF" // here, you must also update the reference to // "SimpleWCF" in Web.config. public class SimpleWCF : ISimpleWCF { #region ISimpleWCF Members public string SayHelloToMe(string name) { return string.Format("Hello {0}, how are you today?", name); }
137
public List<Person> GetPeople() { List<Person> ppl = new List<Person>(); ppl.Add(new }); ppl.Add(new }); ppl.Add(new "Ballmer" return ppl; } #endregion } Person() { FirstName = "Tim", LastName = "Heuer" Person() { FirstName = "Zane", LastName = "Heuer" Person() { FirstName = "Steve", LastName = });
Nous avons ici deux mthodes. Lune renvoie un texte et lautre, une srie de personnes. Ici, pas dattributs. Tout se trouve dans linterface implmente par notre classe SimpleWCF :
using using using using using using System; System.Collections.Generic; System.Linq; System.Runtime.Serialization; System.ServiceModel; System.Text;
[ServiceContract] public interface ISimpleWCF { [OperationContract] string SayHelloToMe(string name); [OperationContract] List<Person> GetPeople(); } [DataContract] public class Person { [DataMember]
138
Du ct de notre Silverlight, nous navons pas normment de chose. Juste un textbox pour donner son nom et un textblock pour afficher les rsultats. Un bouton se trouve galement dans notre XAML pour demander laccs au Web service :
<UserControl x:Class="WebServicesApp.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <StackPanel x:Name="OurStack" Orientation="Vertical"> <TextBox x:Name="InputText"></TextBox> <TextBlock x:Name="OutputText"></TextBlock> <ItemsControl x:Name="PeopleList"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding FirstName}" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <Button x:Name="CallServiceButton" Content="Call WCF Simple" Click="CallServiceButton_Click"></Button> </StackPanel> </Grid> </UserControl>
Au niveau de la gestion de lvnement, dans le code attach au chier, nous avons ceci lorsque nous voulons contacter le Web service ASP.NET :
private void CallServiceButton_Click(object sender, RoutedEventArgs e) { // using ASMX Web service SimpleASMX.SimpleAsmxSoapClient proxy = new WebServicesApp.SimpleASMX.SimpleAsmxSoapClient(); proxy.SayHelloToMeCompleted += new EventHandler<WebServicesApp.SimpleASMX .SayHelloToMeCompletedEventArgs>(proxy_SayHelloToMeCompleted); proxy.SayHelloToMeAsync(InputText.Text); }
139
Si nous souhaitons contacter le service WCF avec la mthode simple, nous aurons :
private void CallServiceButton_Click(object sender, RoutedEventArgs e) { // using WCF Web service with simple type SimpleSVC.SimpleWCFClient proxy = new WebServicesApp.SimpleSVC.SimpleWCFClient(); proxy.SayHelloToMeCompleted += new EventHandler<WebServicesApp.SimpleSVC. SayHelloToMeCompletedEventArgs>(proxy_SayHelloToMeCompleted); proxy.SayHelloToMeAsync(InputText.Text); }
Avec exactement la mme mthode indique au-dessus (proxy_SayHelloToMeCompleted) mais utilisant la dnition de WCF :
void proxy_SayHelloToMeCompleted (object sender, WebServicesApp.SimpleSVC.SayHelloToMeCompletedEventArgs e) { OutputText.Text = e.Result; }
Pour contacter la mthode qui renvoie des donnes complexes, nous aurons :
private void CallServiceButton_Click(object sender, RoutedEventArgs e) { // using WCF Web service with complex type SimpleSVC.SimpleWCFClient proxy = new WebServicesApp.SimpleSVC.SimpleWCFClient(); proxy.GetPeopleCompleted += new EventHandler<WebServicesApp. SimpleSVC.GetPeopleCompletedEventArgs>(proxy_GetPeopleCompleted); proxy.GetPeopleAsync(); }
140
Ou, si vous voulez utiliser LINQ pour ltrer les donnes, par exemple rechercher toutes les personnes dont le nom commence par B :
void proxy_GetPeopleCompleted(object sender, WebServicesApp.SimpleSVC.GetPeopleCompletedEventArgs e) { // result is Person[] SimpleSVC.Person[] people = e.Result; var filtered = from ppl in people where ppl.LastName.StartsWith("B") select ppl; PeopleList.Items.Clear(); PeopleList.ItemsSource = people; }
Au niveau du chier de conguration de Silverlight, nous avons ceci (obtenu lorsque nous avons ajout la rfrence au Web service de notre projet ASP.NET :
<configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_ISimpleWCF" maxBufferSize="65536" maxReceivedMessageSize="65536"> <security mode="None" /> </binding> <binding name="SimpleAsmxSoap" maxBufferSize="65536" maxReceivedMessageSize="65536"> <security mode="None" /> </binding> </basicHttpBinding> </bindings>
141
<client> <endpoint address="http://localhost:1597/WebServicesApp_Web/ SimpleWCF.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISimpleWCF" contract="WebServicesApp.SimpleSVC.ISimpleWCF" name="BasicHttpBinding_ISimpleWCF" /> <endpoint address="http://localhost:1597/WebServicesApp_Web/ SimpleAsmx.asmx" binding="basicHttpBinding" bindingConfiguration="SimpleAsmxSoap" contract="WebServicesApp.SimpleASMX.SimpleAsmxSoap" name="SimpleAsmxSoap" /> </client> </system.serviceModel> </configuration>
Au niveau de notre page de test dans le projet ASP.NET, nous avons le code suivant :
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;"> <head runat="server"> <title>Test Page For WebServicesApp</title> </head> <body style="height:100%;margin:0;"> <form id="form1" runat="server" style="height:100%;"> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <div style="height:100%;"> <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/WebServicesApp.xap" Version="2.0" Width="100%" Height="100%" /> </div> </form> </body> </html>
142
ADO.NET/Silverlight
Rendez-vous au chapitre 4, Silverlight et ASP.NET, pour comprendre comment fonctionne ce contrle ASP.NET Silverlight. Lapplication est termine. WCF est une technologie trs vaste. Il existe plusieurs livres sur ce sujet. Si vous souhaitez plus dinformations, nhsitez pas utiliser Google ou Live pour trouver tout ce que vous voulez savoir sur cette brique du Framework .NET.
3.6 ADO.NET/Silverlight
Silverlight peut exploiter directement les donnes sans passer par un Web service. Pour cela, nous utiliserons les mthodes prsentes dans System.Data.Services.Client. Les exemples de cette section explorent lassociation entre des lments Order et Order_Detail de la base de donnes Northwind disponible partir du Centre de tlchargement de Microsoft cette adresse : http://go.microsoft.com/fwlink/?linkid=24758.
Code de lapplication
Ce chapitre ne montrera pas de code complet mais uniquement des parties de code. Si vous voulez voir la totalit du code, rendez-vous la n de cette section. Vous devez garder en tte ce qui a t vu aux chapitres prcdents. Veillez aussi connatre llment XAML Grid qui nous permettra dafficher les donnes.
Notre application contiendra 5 zones. La premire zone est le Grid en question. Il permettra dafficher les donnes que nous allons rcolter :
<Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition Height="25"/> <RowDefinition Height="250"/> <RowDefinition Height="25"/> <RowDefinition Height="250"/> </Grid.RowDefinitions>
Le deuxime lment constituant notre interface est un StackPanel contenant deux boutons :
<StackPanel Orientation="Horizontal" Grid.Row="0"> <Button Content="Get Data" Width="75" Height="20" Margin="10"
143
Ensuite, nous avons besoin de deux TextBlock : un pour afficher le client concern et lautre pour afficher dventuelles erreurs :
<TextBlock x:Name="CustomerBlock" Grid.Row="1" Text="Customers:" Grid.Column="0" FontFamily="Calibri"/> <TextBlock x:Name="textBlock" Grid.Row="3" Grid.Column="0" FontFamily="Calibri"/>
Il nous faudra ensuite deux DataGrid pour afficher les clients et les commandes associes aux clients :
<data:DataGrid Name="dataGridCustomers" Grid.Row="2" Margin="20" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid> <data:DataGrid Name="dataGridOrders" Grid.Row="4" Margin="20" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid>
Linterface utilisateur Silverlight complte est dnie dans lexemple XAML suivant :
<UserControl x:Class="SilverlightClientApp4.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System .Windows.Controls.Data" Width="800" Height="600">
144
ADO.NET/Silverlight
<Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition Height="25"/> <RowDefinition Height="250"/> <RowDefinition Height="25"/> <RowDefinition Height="250"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0"> <Button Content="Get Data" Width="75" Height="20" Margin="10" Click="OnGetCustomers"/> <Button Content="Get Orders" Width="75" Height="20" Margin="10" Click="OnGetOrders"/> </StackPanel> <TextBlock x:Name="CustomerBlock" Grid.Row="1" Text="Customers:" Grid.Column="0" FontFamily="Calibri"/> <data:DataGrid Name="dataGridCustomers" Grid.Row="2" Margin="20" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid> <TextBlock x:Name="textBlock" Grid.Row="3" Grid.Column="0" FontFamily="Calibri"/> <data:DataGrid Name="dataGridOrders" Grid.Row="4" Margin="20" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid> </Grid> </UserControl>
145
Du ct du code, nous avons 6 actions effectuer. Dabord il faut crer linstance de la classe DataServiceContext de type NorthwindEntities :
NorthwindEntities svcContext; void OnLoaded(object sender, EventArgs args) { svcContext = new NorthwindEntities( new Uri("Northwind.svc", UriKind.Relative)); dataGridCustomers.AutoGeneratingColumn += dataGridCustomers_AutoGeneratingColumn; obsvCollCustomers = new ObservableCollection<Customer>(); OnGetCustomers(null, null); }
Dans la mthode OnGetCustomers, nous allons rechercher tous les clients dont le pays est USA :
void OnGetCustomers(object sender, EventArgs args) { DataServiceQuery<Customer> query = (DataServiceQuery<Customer>) (from customer in svcContext.Customers where customer.Country == "USA" select customer); try { query.BeginExecute(GetCustomersCallback, query); } catch (DataServiceRequestException ex) { textBlock.Text = "OnGetCustomers Error: " + ex.Response.ToString(); } dataGridOrders.DataContext = null; }
Nous avons utilis ici une mthode de CallBack. Cette mthode sexcute lorsque le traitement quon a dni au mme moment est termin. On obtient le rsultat en paramtre de cette fonction CallBack :
void GetCustomersCallback(IAsyncResult result) {
146
ADO.NET/Silverlight
try { DataServiceQuery<Customer> queryResult = (DataServiceQuery<Customer>)result.AsyncState; IEnumerable<Customer> ienumResults = queryResult.EndExecute(result); obsvCollCustomers = new ObservableCollection<Customer>(); foreach (var item in ienumResults) { obsvCollCustomers.Add(item); } Dispatcher.BeginInvoke(() => { dataGridCustomers.DataContext = obsvCollCustomers; }); } catch (DataServiceRequestException ex) { textBlock.Text = "GetCustomersCallback Error: " + ex.Response.ToString(); } }
Nous avons dni un vnement sur la gestion des colonnes. Nous supprimerons deux colonnes qui nont pas lieu dtre dans ce Grid-l. Pour ce faire, nous devons annuler la gnration si nous rencontrons ces deux colonnes :
void dataGridCustomers_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { if (e.PropertyName == "CustomerDemographics" || e.PropertyName == "Orders") { e.Cancel = true; } }
Il faut ensuite grer la liste des commandes dun client. Pour cela, nous avions cr un bouton. Sur le clic du bouton Get Order, nous allons appeler la mthode OnGetOrders :
ObservableCollection<Order> obsvCollCustomerOrders;
147
void OnGetOrders(object sender, EventArgs args) { Customer selectedCustomer = (Customer)dataGridCustomers.SelectedItem; try { svcContext.BeginLoadProperty(selectedCustomer, "Orders", OnPropertyLoading, selectedCustomer); } catch (DataServiceRequestException ex) { textBlock.Text = "OnGetOrders Error: " + ex.Response.ToString(); } }
Nous demandons ici notre DataContext les commandes du client actuellement slectionn :
svcContext.BeginLoadProperty(selectedCustomer, "Orders", OnPropertyLoading, selectedCustomer);
De la mme manire, lorsque le rsultat aura t rapatri, la mthode OnPropertyLoading sera appele et cette fonction traitera les diffrentes informations, comme lajout dans le DataGrid :
void OnPropertyLoading(IAsyncResult result) { void OnPropertyLoading(IAsyncResult result) { Customer resultCustomer = result.AsyncState as Customer; try { svcContext.EndLoadProperty(result); if (resultCustomer.Orders.Count == 0) { textBlock.Text = "Customer has no orders"; dataGridOrders.DataContext = null; return; } else textBlock.Text = "Customer orders:";
148
ADO.NET/Silverlight
obsvCollCustomerOrders = new ObservableCollection<Order>(); foreach (Order order in resultCustomer.Orders) { obsvCollCustomerOrders.Add(order); } Dispatcher.BeginInvoke(() => { dataGridOrders.DataContext = obsvCollCustomerOrders; }); } catch (DataServiceRequestException ex) { textBlock.Text = "OnPropertyLoading Error: " + ex.Response.ToString(); } }
using SilverlightClientApp4.NorthwindSvc; using System.Data.Services.Client; using System.Collections.ObjectModel; namespace SilverlightClientApp4 { public partial class Page : UserControl { NorthwindEntities svcContext; ObservableCollection<Customer> obsvCollCustomers; ObservableCollection<Order> obsvCollCustomerOrders; public Page() {
149
InitializeComponent(); this.Loaded += OnLoaded; } void OnLoaded(object sender, EventArgs args) { svcContext = new NorthwindEntities( new Uri("Northwind.svc", UriKind.Relative)); dataGridCustomers.AutoGeneratingColumn += dataGridCustomers_AutoGeneratingColumn; obsvCollCustomers = new ObservableCollection<Customer>(); OnGetCustomers(null, null); } void OnGetOrders(object sender, EventArgs args) { Customer selectedCustomer = (Customer)dataGridCustomers.SelectedItem; try { svcContext.BeginLoadProperty(selectedCustomer, "Orders", OnPropertyLoading, selectedCustomer); } catch (DataServiceRequestException ex) { textBlock.Text = "OnGetOrders Error: " + ex.Response.ToString(); } } void OnPropertyLoading(IAsyncResult result) { Customer resultCustomer = result.AsyncState as Customer; try { svcContext.EndLoadProperty(result); if (resultCustomer.Orders.Count == 0) { textBlock.Text = "Customer has no orders";
150
ADO.NET/Silverlight
dataGridOrders.DataContext = null; return; } else textBlock.Text = "Customer orders:"; obsvCollCustomerOrders = new ObservableCollection<Order>(); foreach (Order order in resultCustomer.Orders) { obsvCollCustomerOrders.Add(order); } Dispatcher.BeginInvoke(() => { dataGridOrders.DataContext = obsvCollCustomerOrders; }); } catch (DataServiceRequestException ex) { textBlock.Text = "OnPropertyLoading Error: " + ex.Response.ToString(); } } void OnGetCustomers(object sender, EventArgs args) { DataServiceQuery<Customer> query = (DataServiceQuery<Customer>) (from customer in svcContext.Customers where customer.Country == "USA" select customer); try { query.BeginExecute(GetCustomersCallback, query); } catch (DataServiceRequestException ex) { textBlock.Text = "OnGetCustomers Error: " + ex.Response.ToString(); } dataGridOrders.DataContext = null; } void GetCustomersCallback(IAsyncResult result) {
151
try { DataServiceQuery<Customer> queryResult = (DataServiceQuery<Customer>)result.AsyncState; IEnumerable<Customer> ienumResults = queryResult.EndExecute(result); obsvCollCustomers = new ObservableCollection<Customer>(); foreach (var item in ienumResults) { obsvCollCustomers.Add(item); } Dispatcher.BeginInvoke(() => { dataGridCustomers.DataContext = obsvCollCustomers; }); } catch (DataServiceRequestException ex) { textBlock.Text = "GetCustomersCallback Error: " + ex.Response.ToString(); } } void dataGridCustomers_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { if (e.PropertyName == "CustomerDemographics" || e.PropertyName == "Orders") { e.Cancel = true; } } } }
152
De nombreux sites Internet diffusent des informations de mto via Web services. Si vous avez un iPhone et que vous ayez dj manipul lapplication mto, vous avez alors dj utilis le Web service mto de Yahoo. En effet, lapplication a besoin dune connexion data pour aller rechercher linformation sur Yahoo et vous lafficher ensuite. Nous utiliserons un autre Web service. Vous pourrez trouver un grand nombre de services sur le site suivant : http://a4472706772.api.wxbug.net/. La premire chose faire est dajouter la rfrence au Web service dans votre projet Silverlight. Ceci cre un chier ServiceReferences.ClientCong :
<configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="WeatherBugWebServicesSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://a4472706772.api.wxbug.net/ weatherservice.asmx" binding="basicHttpBinding" bindingConfiguration="WeatherBugWebServicesSoap" contract="WeatherService.WeatherBugWebServicesSoap" name="WeatherBugWebServicesSoap" /> </client> </system.serviceModel> </configuration>
153
Pour notre interface, nous allons utiliser un grand nombre dimages. Vous pourrez retrouver tout ce code et les images sur le site de Micro Application :
<UserControl.Resources> <ImageBrush ImageSource="Resources/BLUE-base.png" x:Key="blueBase" /> <ImageBrush ImageSource="Resources/GRAY-base.png" x:Key="grayBase" /> <ImageBrush ImageSource="Resources/divider-vertical.png" x:Key="dividerVertical" Opacity="0.6" /> <ImageBrush ImageSource="Resources/divider-horizontal.png" x:Key="dividerHorizontal" Opacity="0.6" /> <BitmapImage UriSource="Resources/BLACK-highlight-01.png" x:Key="blackHighlight" /> <BitmapImage UriSource="Resources/undocked_cloudy.png" x:Key="CloudyBig" /> <BitmapImage UriSource="Resources/26.png" x:Key="Cloudy" /> <BitmapImage UriSource="Resources/undocked_few-showers.png" x:Key="FewShowersBig" /> <BitmapImage UriSource="Resources/5.png" x:Key="FewShowers" /> <BitmapImage UriSource="Resources/undocked_foggy.png" x:Key="FoggyBig" /> <BitmapImage UriSource="Resources/19.png" x:Key="Foggy" /> <BitmapImage UriSource="Resources/undocked_hail.png" x:Key="HailBig" /> <BitmapImage UriSource="Resources/17.png" x:Key="Hail" /> <BitmapImage UriSource="Resources/undocked_partly-cloudy.png" x:Key="PartlyCloudyBig" /> <BitmapImage UriSource="Resources/29.png" x:Key="PartlyCloudy" /> <BitmapImage UriSource="Resources/undocked_rainy.png" x:Key="RainyBig" /> <BitmapImage UriSource="Resources/8.png" x:Key="Rainy" /> <BitmapImage UriSource="Resources/undocked_snow.png" x:Key="SnowBig" /> <BitmapImage UriSource="Resources/13.png" x:Key="Snow" /> <BitmapImage UriSource="Resources/undocked_sun.png" x:Key="SunBig" /> <BitmapImage UriSource="Resources/undocked_moon-full.png" x:Key="MoonBig" /> <BitmapImage UriSource="Resources/31.png" x:Key="Sun" /> <BitmapImage UriSource="Resources/undocked_thunderstorm.png" x:Key="ThunderstormBig" /> <BitmapImage UriSource="Resources/1.png" x:Key="Thunderstorm" /> <BitmapImage UriSource="Resources/undocked_windy.png" x:Key="WindyBig" /> <BitmapImage UriSource="Resources/23.png" x:Key="Windy" />
154
Pour plus dinformations sur le binding, rendez-vous au chapitre Le langage XAML, o lon explique son fonctionnement exact. Voici le XAML complet de lapplication qui utilise les ressources :
<UserControl x:Class="WeatherWidget.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="320" Height="240" > <UserControl.Resources> <ImageBrush ImageSource="Resources/BLUE-base.png" x:Key="blueBase" /> <ImageBrush ImageSource="Resources/GRAY-base.png" x:Key="grayBase" /> <ImageBrush ImageSource="Resources/divider-vertical.png" x:Key="dividerVertical" Opacity="0.6" /> <ImageBrush ImageSource="Resources/divider-horizontal.png" x:Key="dividerHorizontal" Opacity="0.6" /> <BitmapImage UriSource="Resources/BLACK-highlight-01.png" x:Key="blackHighlight" /> <BitmapImage UriSource="Resources/undocked_cloudy.png" x:Key="CloudyBig" /> <BitmapImage UriSource="Resources/26.png" x:Key="Cloudy" /> <BitmapImage UriSource="Resources/undocked_few-showers.png" x:Key="FewShowersBig" /> <BitmapImage UriSource="Resources/5.png" x:Key="FewShowers" /> <BitmapImage UriSource="Resources/undocked_foggy.png" x:Key="FoggyBig" /> <BitmapImage UriSource="Resources/19.png" x:Key="Foggy" /> <BitmapImage UriSource="Resources/undocked_hail.png" x:Key="HailBig" /> <BitmapImage UriSource="Resources/17.png" x:Key="Hail" /> <BitmapImage UriSource="Resources/undocked_partly-cloudy.png" x:Key="PartlyCloudyBig" /> <BitmapImage UriSource="Resources/29.png" x:Key="PartlyCloudy" /> <BitmapImage UriSource="Resources/undocked_rainy.png"
155
x:Key="RainyBig" /> <BitmapImage UriSource="Resources/8.png" x:Key="Rainy" /> <BitmapImage UriSource="Resources/undocked_snow.png" x:Key="SnowBig" /> <BitmapImage UriSource="Resources/13.png" x:Key="Snow" /> <BitmapImage UriSource="Resources/undocked_sun.png" x:Key="SunBig" /> <BitmapImage UriSource="Resources/undocked_moon-full.png" x:Key="MoonBig" /> <BitmapImage UriSource="Resources/31.png" x:Key="Sun" /> <BitmapImage UriSource="Resources/undocked_thunderstorm.png" x:Key="ThunderstormBig" /> <BitmapImage UriSource="Resources/1.png" x:Key="Thunderstorm" /> <BitmapImage UriSource="Resources/undocked_windy.png" x:Key="WindyBig" /> <BitmapImage UriSource="Resources/23.png" x:Key="Windy" /> <SolidColorBrush Color="White" Opacity="0.5" x:Key="zipCodeBackground" /> </UserControl.Resources> <Canvas x:Name="LayoutRoot" Width="264" Height="194" Background="{StaticResource blueBase}"> <Canvas Canvas.Top="13" Canvas.Left="13" Width="230" Height="160"> <StackPanel x:Name="ConditionsScreen" > <Canvas Height="90"> <Image x:Name="ConditionsOverlay" Margin="-13,-13,0,0" Source="{StaticResource SunBig}"/> <StackPanel> <TextBlock Width="225" Height="37" TextAlignment="Right" FontSize="34" x:Name="TodayTemp" /> <TextBlock Width="225" Height="14" TextAlignment="Right" x:Name="TodayDescription" /> <TextBlock Width="225" Height="14" TextAlignment="Right" x:Name="TodayRange" /> <TextBlock Width="225" Height="14" TextAlignment="Right" x:Name="City" Text="Fetching data..." /> </StackPanel> </Canvas> <StackPanel Orientation="Horizontal" Height="53"> <Canvas Width="71" Background="{StaticResource dividerVertical}"
156
Margin="5, 0, 0, 0"> <TextBlock FontSize="11" x:Name="TomorrowName" Foreground="White" Opacity="0.5" /> <Image x:Name="TomorrowImage" Canvas.Top="17" Canvas.Left="23" /> <TextBlock Canvas.Top="20" x:Name="TomorrowHi" Foreground="White" /> <TextBlock Canvas.Top="35" x:Name="TomorrowLo" Foreground="White" Opacity="0.5" /> </Canvas> <Canvas Width="71" Background="{StaticResource dividerVertical}" Margin="5, 0, 0, 0"> <TextBlock FontSize="11" x:Name="DayAfterName" Foreground="White" Opacity="0.5" /> <Image x:Name="DayAfterImage" Canvas.Top="17" Canvas.Left="23" /> <TextBlock Canvas.Top="20" x:Name="DayAfterHi" Foreground="White" /> <TextBlock Canvas.Top="35" x:Name="DayAfterLo" Foreground="White" Opacity="0.5" /> </Canvas> <Canvas Width="71" Margin="5, 0, 0, 0"> <TextBlock FontSize="11" x:Name="TwoDaysAwayName" Foreground="White" Opacity="0.5" /> <Image x:Name="TwoDaysAwayImage" Canvas.Top="17" Canvas.Left="23" /> <TextBlock Canvas.Top="20" x:Name="TwoDaysAwayHi" Foreground="White" /> <TextBlock Canvas.Top="35" x:Name="TwoDaysAwayLo" Foreground="White" Opacity="0.5" /> </Canvas> </StackPanel> <StackPanel Height="17" Background="{StaticResource dividerHorizontal}" Orientation="Horizontal" > <TextBlock Text="Refresh data" Margin="5, 0, 5, 0" Width="105" Foreground="White" Opacity="0.5" MouseLeftButtonUp="TextBlock_MouseLeft ButtonUp_Refresh" /> <TextBlock Text="Change ZIP" Margin="5, 0, 5, 0" Width="105" TextAlignment="Right" Foreground="White" Opacity="0.5" MouseLeftButtonUp="TextBlock_MouseLeft ButtonUp_Zip" /> </StackPanel>
157
</StackPanel> <StackPanel x:Name="ZipCodeScreen" HorizontalAlignment="Center" Visibility="Collapsed" Width="230"> <TextBlock Margin="0, 50, 0, 0" Text="Please enter ZIP code:" Width="130" /> <StackPanel Orientation="Horizontal" Width="120" > <TextBox x:Name="ZipCode" Width="55" MaxLength="5" FontSize="14" Background="{StaticResource zipCodeBackground}" /> <Button Content="Change" Click="Button_Click" Margin="10, 0, 0, 0" /> </StackPanel> <TextBlock Margin="0, 20, 0, 0" Width="220" Text="Weather data courtesy of WeatherBug." /> </StackPanel> <Image IsHitTestVisible="False" Source="{StaticResource blackHighlight}" /> </Canvas> </Canvas> </UserControl>
Dans le code C# attach ce chier XAML, nous avons tout ce qui est connexion au Web service. Cest l que nous irons rechercher les donnes concernant la mto. Nous avons une classe Page qui drive de UserControl, comme dans chaque projet Silverlight :
using using using using using using using using using System; System.ServiceModel; System.Windows; System.Windows.Controls; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; WeatherWidget.WeatherService; System.Windows.Browser;
158
FewShowers, Foggy, Hail, PartlyCloudy, Rainy, Snow, Sun, Moon, Thunderstorm, Windy } public partial class Page : UserControl { public Page() { } } }
Nous avons une numration qui permet de choisir limage qui sera affiche. Dans les ressources, nous avons dclar deux arrire-plans. Un pour les bonnes journes et lautre pour les mauvaises journes. Par dfaut, le soleil est affich :
<Canvas x:Name="LayoutRoot" Width="264" Height="194" Background="{StaticResource blueBase}">
Grce lajout de la rfrence vers le Web service, nous pouvons crer un projet de type :
WeatherBugWebServicesSoapClient
private WeatherBugWebServicesSoapClient proxy;
159
Dans le constructeur de notre application, nous allons crer et initialiser ce qui concerne notre Web service :
public Page() { // Required to initialize variables InitializeComponent(); // Check that user provided an API key if (!String.IsNullOrEmpty(apiCode)) { // Initialize Web service proxy = new WeatherBugWebServicesSoapClient(); // Create event handlers for service methods proxy.GetForecastByUSZipCodeCompleted += new EventHandler<GetForecastByUSZipCodeCompletedEventArgs> (proxy_GetForecastByUSZipCodeCompleted); proxy.GetLiveWeatherByUSZipCodeCompleted += new EventHandler<GetLiveWeatherByUSZipCodeCompletedEventArgs> (proxy_GetLiveWeatherByUSZipCodeCompleted); // Update display UpdateDisplay(); } else { // If no API key was provided, alert the user and disable the UI City.Text = "No API key provided"; ConditionsScreen.IsHitTestVisible = false; ZipCodeScreen.IsHitTestVisible = false; } }
La premire fonction utilise est InitializeComponent. Elle est prsente dans toutes les applications. Elle permet dinitialiser les diffrents composants XAML de lapplication.
160
161
Nous avons dclar ce proxy prcdemment dans le code an davoir accs cette variable partout dans le reste des fonctions. Cest donc un variable globale. Nous ajoutons aprs deux vnements qui seront intercepts par les deux fonctions suivantes :
j j
proxy_GetForecastByUSZipCodeCompleted ; proxy_GetLiveWeatherByUSZipCodeCompleted.
Le type des arguments est dni dans la rfrence. Nous avons par exemple GetLiveWeatherByUSZipCodeCompletedEventArgs :
[System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] public partial class GetLiveWeatherByUSZipCodeCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { private object[] results; public GetLiveWeatherByUSZipCodeCompletedEventArgs (object[] results, System.Exception exception, bool cancelled, object userState) : base(exception, cancelled, userState) { this.results = results; } public WeatherWidget.WeatherService.LiveWeatherData Result { get { base.RaiseExceptionIfNecessary(); return ((WeatherWidget.WeatherService.LiveWeatherData) (this.results[0])); } } }
162
Ce code est automatiquement gnr par lajout de la rfrence au Web service. Il est toutefois important de savoir comment cela fonctionne. Vous serez parfois dans lobligation de dclarer vous-mme ces objets. Quoi quil en soit, Visual Studio gre pour vous une grande partie du projet. Les deux fonctions vnements doivent tre dclares. La premire permet de connatre les prvisions mto et la deuxime le temps actuel :
void proxy_GetForecastByUSZipCodeCompleted(object sender, GetForecastByUSZipCodeCompletedEventArgs e) { ArrayOfAnyType forecast = e.Result; // Set the remaining three days, except for today for (int i = 1; i < 4; i++) { ApiForecastData today = (ApiForecastData)forecast[i]; setDay(i, today.Title, parseTemp(today.TempHigh), parseTemp(today.TempLow), int.Parse(today.ConditionID)); } // Then call for todays live data, and pass the conditions well need later proxy.GetLiveWeatherByUSZipCodeAsync(zipCode.ToString(), UnitType.English, apiCode, forecast[0]); } void proxy_GetLiveWeatherByUSZipCodeCompleted(object sender, GetLiveWeatherByUSZipCodeCompletedEventArgs e) { LiveWeatherData today = e.Result; ApiForecastData todayForecast = (ApiForecastData)e.UserState; // Set todays conditions setToday(today.City, todayForecast.ShortPrediction, float.Parse(today.Temperature), parseTemp(today.TemperatureHigh), parseTemp(today.TemperatureLow), int.Parse(todayForecast.ConditionID), !todayForecast.IsNight); }
163
Dans la premire fonction, nous avons besoin de setDay. Cette fonction va rechercher les lments XAML pour y afficher les bonnes valeurs, au bon endroit. Elle emploie une fonction "utilitaire" pour convertir le temps :
static int parseTemp(string input) { int temp; // Remove trailing unrecognized characters input = input.TrimEnd(\xFFFD); // If the hi/lo is unavailable, set it to 0 if (String.IsNullOrEmpty(input) || input == "--") { temp = 0; } else { temp = int.Parse(input); } return temp; }
164
break; case 3: default: todayName = TwoDaysAwayName; todayHi = TwoDaysAwayHi; todayLo = TwoDaysAwayLo; todayImage = TwoDaysAwayImage; break; } todayName.Text = name.ToString(); todayHi.Text = hi.ToString() + ""; todayLo.Text = lo.ToString() + ""; todayImage.Source = mapConditionsToImage(mapCodesToConditions (weatherConditions, true), false); }
On voit que dans le switch, on recherche les bons lments XAML au bon endroit. Cela se fera en fonction du choix de laffichage des prvisions pour le jour un, deux ou trois et de loffset qui est pass en paramtre. Ensuite, on indique les bonnes valeurs, valeurs passes en paramtre de notre fonction. On mappe aprs limage qui correspond aux valeurs :
private BitmapImage mapConditionsToImage(WeatherConditions weatherConditions, bool isBig) { // Build the resource name - something like RainyBig string resourceName = Enum.GetName(typeof(WeatherConditions), weatherConditions) + (isBig ? "Big" : ""); return (BitmapImage)Resources[resourceName]; }
La
valeur
passe
en
paramtre
est
obtenue
laide
dune
fonction
nous lavons place la n de cet exemple, dans une partie portant le nom de la fonction. Lautre fonction dont nous avons besoin est celle qui va afficher le temps quil fait actuellement dehors. Cette fonction se nomme SetToday et nous lavons utilise dans proxy_GetLiveWeatherByUSZipCodeCompleted. Elle suit plus ou moins le mme principe :
private void setToday(string cityName, string description, float temp, int hi, int lo, int weatherConditions, bool isDay)
165
{ // Set the weather parameters City.Text = cityName; TodayTemp.Text = temp.ToString() + ""; TodayDescription.Text = description; TodayRange.Text = hi + " - " + lo + ""; // Set the correct background according to the conditions WeatherConditions currentConditions = mapCodesToConditions(weatherConditions, isDay); // Set correct main image according to the conditions ConditionsOverlay.Source = mapConditionsToImage (currentConditions, true); if (!isDay || (currentConditions == WeatherConditions.Moon) || (currentConditions == WeatherConditions.Cloudy) || (currentConditions == WeatherConditions.Foggy) || (currentConditions == WeatherConditions.Hail) || (currentConditions == WeatherConditions.Rainy) || (currentConditions == WeatherConditions.Snow) || (currentConditions == WeatherConditions.Thunderstorm)) { LayoutRoot.Background = (ImageBrush)Resources["grayBase"]; } else { LayoutRoot.Background = (ImageBrush)Resources["blueBase"]; } }
On met une valeur quelques champs et on fait appel aux mmes mthodes que dans la premire fonction : mapConditionsToImage et mapCodesToConditions. Le constructeur fait ensuite appel une fonction UpdateDisplay pour mettre jour toutes les donnes :
private void UpdateDisplay() { // Call for the 4 day forecast first proxy.GetForecastByUSZipCodeAsync (zipCode.ToString(), UnitType.English, apiCode); }
166
Cette mthode dclenche les deux autres vnements qui mettent jour les donnes de notre application Silverlight. Nous lutiliserons un peu partout dans notre code. Comme indiqu dans la remarque prcdemment, nous disposons dun bouton qui permet de mettre jour le code postal. Nous avons donc ajout un vnement sur le clic du bouton :
private void Button_Click(object sender, RoutedEventArgs e) { bool error = false; if (ZipCode.Text.Length == ZipCode.MaxLength) { try { zipCode = int.Parse(ZipCode.Text); UpdateDisplay(); // Switch to conditions screen ConditionsScreen.Visibility = Visibility.Visible; ZipCodeScreen.Visibility = Visibility.Collapsed; } catch (FormatException) { error = true; } } else { error = true; } if(error) ZipCode.Foreground = new SolidColorBrush(Colors.Red); }
Ce bouton va rechercher le code postal dans une textbox, le transforme en chiffre et met jour le contenu de notre application. Nous vnements grer du ct de notre code. TextBlock_MouseLeftButtonUp_Zip est lun de ces vnements. Il permet en fait dafficher la textbox pour modier le code postal :
private void TextBlock_MouseLeftButtonUp_Zip (object sender, MouseButtonEventArgs e) { ZipCode.Text = "";
avons
encore
deux
167
ZipCode.Foreground = new SolidColorBrush (Colors.Black); // Switch to ZIP code selection screen ConditionsScreen.Visibility = Visibility.Collapsed; ZipCodeScreen.Visibility = Visibility.Visible; }
Enn, nous disposons dun bouton permettant de rafrachir le contenu. Pour cela, il suffit dappeler la mthode dj dclare prcdemment :
private void TextBlock_MouseLeftButtonUp_Refresh (object sender, MouseButtonEventArgs e) { UpdateDisplay(); }
Lapplication du ct Silverlight est termine. Reste crer une page HTML de test pour afficher notre application dans un navigateur. Au niveau de notre page HTML, rien de trs difficile :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <!-- saved from url=(0014)about:internet --> <head> <title>Silverlight Project Test Page </title> <style type="text/css"> html, body { height: 100%; overflow: auto; } body { padding: 0; margin: 0; } #silverlightControlHost { height: 100%; } </style> <script type="text/javascript"> function onSilverlightError(sender, args) {
168
var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; } var errorType = args.ErrorType; var iErrorCode = args.ErrorCode; var errMsg = "Unhandled Error in Silverlight 2 Application " + appSource + "\n" ; errMsg += "Code: "+ iErrorCode + " \n"; errMsg += "Category: " + errorType + " \n"; errMsg += "Message: " + args.ErrorMessage + " \n"; if (errorType == "ParserError") { errMsg += "File: " + args.xamlFile + " \n"; errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } errMsg += "MethodName: " + args.methodName + " \n"; } throw new Error(errMsg); } </script> </head> <body> <!-- Runtime errors from Silverlight will be displayed here. This will contain debugging information and should be removed or hidden when debugging is completed --> <div id=errorLocation style="font-size: small;color: Gray;"> </div> <div id="silverlightControlHost"> <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"> <param name="source"
169
value="ClientBin/WeatherWidget.xap"/> <param name="onerror" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="2.0.30923.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/> </a> </object> <iframe visibility=hidden height=0 width=0 border=0px></iframe> </div> </body> </html>
Notre premier exemple est termin. Nous avons vu ici comment contacter un Web service. Dans le prochain exemple, nous apprendrons manipuler les donnes RSS.
MapCodesToConditions
static WeatherConditions mapCodesToConditions(int weatherConditions, bool isDay) { WeatherConditions conditions; switch (weatherConditions) { case 1: case 13: case 24: case 34: case 66: case 68: case 73: conditions = WeatherConditions.Cloudy; break; case 9: case 19: case 21: case 25:
170
case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case
27: 28: 32: 36: 46: 47: 48: 49: 56: 57: 60: 61: 84: 85: 86: 90: 91: 92: 96: 97: 98: 99: 100: 101: 120: 121: 122: 123: 124: 125: 129: 130: 131: 135: 136: 137: 140: 142: 144: 145: 152: 153: 155: 157: conditions = WeatherConditions.FewShowers; break; case 23:
171
case 33: case 51: conditions = WeatherConditions.Foggy; break; case 2: case 3: case 16: case 67: case 71: case 72: conditions = WeatherConditions.PartlyCloudy; break; case 5: case 14: case 15: case 20: case 38: case 41: case 42: case 45: case 52: case 58: case 59: case 63: case 81: case 82: case 83: case 87: case 88: case 89: case 108: case 109: case 110: case 114: case 115: case 116: case 132: case 133: case 134: case 139: case 141: case 148: case 150: case 156: conditions = WeatherConditions.Rainy; break; case 8:
172
case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case case
11: 12: 29: 39: 40: 43: 44: 54: 55: 62: 69: 74: 78: 79: 80: 102: 103: 104: 111: 112: 113: 117: 118: 119: 126: 127: 128: 138: 146: 149: 151: 154: conditions = WeatherConditions.Snow; break; case 0: case 7: case 10: case 17: case 26: case 31: case 35: case 37: case 64: case 65: case 70: case 75: case 76:
173
case 77: default: conditions = (isDay) ? WeatherConditions.Sun : WeatherConditions.Moon; break; case 6: case 18: case 22: case 30: case 53: case 93: case 94: case 95: case 105: case 106: case 107: case 143: case 147: conditions = WeatherConditions.Thunderstorm; break; case 50: conditions = WeatherConditions.Windy; break; } return conditions; }
174
Pour le header, rien de trs compliqu : une textbox et un bouton, peu de choses prs :
<StackPanel Orientation="Vertical" Width="845" > <TextBlock Text="Enter feed address below. If this control and the feed are not hosted on the same domain, add a clientaccesspolicy.xml or crossdomain.xml file to domain where the feed is hosted to enable cross-domain access." TextWrapping="Wrap" FontSize="14" /> <StackPanel Orientation="Horizontal" Margin="0, 10, 0, 10"> <TextBox Width="400" x:Name="feedAddress" FontSize="14"/> <Button Content="Fetch feed" Margin="20, 0, 0, 0" FontSize="14" Click="Button_Click" /> </StackPanel>
Ensuite, pour les deux colonnes du bas qui affichent le contenu, nous avons une ListBox et un StackPanel avec un ScrollViewer pour afficher le texte :
<StackPanel Orientation="Horizontal" Margin="0, 10, 0, 10"> <TextBox Width="400" x:Name="feedAddress" FontSize="14"/> <Button Content="Fetch feed" Margin="20, 0, 0, 0" FontSize="14" Click="Button_Click" /> </StackPanel> <StackPanel Orientation="Horizontal"> <ListBox x:Name="itemsList" ItemsSource="{Binding}" Width="325" Height="500" SelectionChanged="itemsList_SelectionChanged" Visibility="Collapsed"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Title.Text, Converter={StaticResource htmlSanitizer}}" TextWrapping="Wrap" Width="300" FontSize="14"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <StackPanel x:Name="itemContent" Orientation="Vertical" Width="500" Height="500" Margin="20, 0, 0, 0" Visibility="Collapsed"> <HyperlinkButton Content="{Binding Title.Text, Converter={StaticResource htmlSanitizer}}"
175
NavigateUri="{Binding Links, Converter={StaticResource linkFormatter}}" FontSize="16" TargetName="_blank" /> <TextBlock Text="{Binding PublishDate}" TextWrapping="Wrap" FontSize="14" /> <ScrollViewer Height="445" Margin="0, 10, 0, 0"> <TextBlock Text="{Binding Summary.Text, Converter={StaticResource htmlSanitizer}}" TextWrapping="Wrap" FontSize="14"/> </ScrollViewer> </StackPanel> </StackPanel>
Sans oublier que nous avons besoin de deux ressources stockes au tout dbut de notre code dans les ressources de lusercontrol :
<UserControl.Resources> <local:HtmlSanitizer x:Key="htmlSanitizer"/> <local:LinkFormatter x:Key="linkFormatter"/> </UserControl.Resources>
Au niveau du code, rien dextraordinaire non plus. Dans le constructeur, nous mettrons une valeur par dfaut dans la textbox :
public Page() { InitializeComponent(); // Start with a default feed feedAddress.Text = "http://feeds.wired.com/wired/index?format=xml"; }
Sur le clic du bouton, nous allons instancier un objet WebClient. Cet objet ira tlcharger le contenu. Nous pourrons ensuite traiter le contenu avec notre objet SyndicationFeed, laide dun vnement.
Le code asynchrone
On voit souvent le mot async utilis dans le code. En fait, il sagit de traiter plusieurs choses en parallle pour augmenter la vitesse dexcution. Ce que nous faisons ici, cest dire : "Va rechercher le contenu et notie-nous dun vnement quand tu as ni". Cest pour cela que lvnement sappelle client_OpenReadCompleted, completed signiant complet.
176
private void Button_Click(object sender, RoutedEventArgs e) { itemsList.Visibility = Visibility.Collapsed; itemContent.Visibility = Visibility.Collapsed; // Make HTTP request to get feed WebClient client = new WebClient(); client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted); client.OpenReadAsync(new Uri(feedAddress.Text)); }
Le rsultat sera transmis en paramtre de lvnement. Nous pouvons donc le rcuprer dans la fonction client_OpenReadCompleted qui sera appele lorsque le tlchargement du contenu sera ni :
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { // Load feed into SyndicationFeed XmlReader reader = XmlReader.Create(e.Result); SyndicationFeed feed = SyndicationFeed.Load(reader); // Set up databinding itemsList.DataContext = (feed as SyndicationFeed).Items; itemsList.Visibility = Visibility.Visible; } }
Nous avions dans les ressources deux objets qui sont des converters. On utilise ces objets pour convertir une valeur. Par exemple, nous allons recevoir un texte mais il faut quil soit bien format. Pour cette raison, nous avons une classe HtmlSanitizer :
public class HtmlSanitizer : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { // Remove HTML tags and empty newlines and spaces string returnString = Regex.Replace(value as string, "<.*?>", "");
177
returnString = Regex.Replace(returnString, @"\n+\s+", "\n\n"); // Decode HTML entities returnString = HttpUtility.HtmlDecode(returnString); return returnString; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
Lobjet implmente une interface IValueConverter. Cest de cette manire que le programme sait que cest un converter. Nous avons la mme chose pour LinkFormatter :
public class LinkFormatter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { // Get the first link - thats the link to the post return ((Collection<SyndicationLink>)value).FirstOrDefault().Uri; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
Au niveau de notre page de test HTML, nous avons la mme chose que dhabitude :
<div id="Div1"> <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"> <param name="source" value="ClientBin/SyndicationFeedReader.xap"/>
178
Check-list
<param name="onerror" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="2.0.30923.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/> </a> </object> <iframe visibility=hidden height=0 width=0 border=0px></iframe> </div>
Nous allons tudier dans le prochain chapitre les concepts avancs de Silverlight. Vous verrez aussi par la suite comment amliorer linsertion de Silverlight lorsque vous utilisez ASP.NET comme technologie serveur.
3.9 Check-list
Dans ce chapitre nous avons tudi :
a lexploitation des sources de donnes SQL ; a lutilisation des Web services ; a LINQ ; a la manipulation XML au travers dun exemple ; a la manipulation de donnes RSS au travers dun exemple.
179
4
4.1 Introduction ASP.NET ................................. 4.2 Les contrles ASP.NET .................................. 4.3 Les contrles ASP.NET pour Silverlight ................ 4.4 Interaction de Silverlight avec la page ............... 4.5 Check-list ................................................. 182 191 198 210 211
Silverlight et ASP.NET
A
SP.NET est une technologie base sur la plateforme .NET de Microsoft qui vous permet de crer des sites web simplement. Plongez-vous dans ce chapitre si vous souhaitez connatre tout ce quil faut savoir sur la conception et le dveloppement dapplications web avec ASP.NET et Silverlight.
Silverlight et ASP.NET
VB.NET successeur de VB ; C#, nouveau langage spcialement conu pour la plateforme .NET ; J# qui a t introduit spcialement pour permettre la rutilisation des blocs crits en J++ et attirer les dveloppeurs Java, etc.
Il en existe bien dautres (Cobol, PHP, ). On notera larrive de deux nouveaux, rcemment :
j j
IronRuby qui, comme son nom lindique, est un driv de Ruby ; IronPython qui, de la mme manire, est un driv de Python.
En rsum, peu importe le langage utilis, Microsoft met votre disposition un ensemble doutils qui vous faciliteront lcriture dune application ou/et dun site Internet. Lensemble de ces outils constitue le Framework .NET. Nous sommes aujourdhui la version 3.5 du Framework .NET. La version 3.0 a t introduite avec Vista. Vous pouvez trouver la version 3.5 sur Internet (voir Les prrequis dans ce chapitre).
ASP.NET
ASP.NET dsigne un ensemble de technologies qui vont vous simplier lcriture dapplications web dynamiques. ASP.NET succde ASP mais ne vous y trompez pas, ce nest pas du tout la mme chose. Le concept a t compltement repens. Dans cet ensemble de technologies on trouvera, par exemple, des outils qui nous permettront de faciliter la gestion de la scurit. En effet, scuriser des pages et crer des espaces membres est un jeu denfants en ASP.NET. De la mme manire, la gestion des donnes est trs simple de prime abord. Si les composants ASP.NET ne suffisent pas, vous avez accs tout ce que le Framework .NET vous propose. Le but ici nest pas de dcrire lensemble des fonctionnalits de ASP.NET mais de vous donner tous les outils et connaissances de base pour crer et comprendre votre premier site ASP.NET.
182
Introduction ASP.NET
Prrequis
Les sceptiques se disent certainement quavec Microsoft, il va falloir payer. Mais ce nest pas le cas. On peut bien programmer avec ASP.NET gratuitement. Il existe en effet une gamme express des produits Microsoft qui vous permet dobtenir des outils suffisants pour la cration de vos premiers projets. Vous pouvez ds lors employer Visual Web Developer Express pour dvelopper vos sites Internet et SQL Server 2005 Express comme base de donnes. Vous trouverez ces deux outils ici : http://msdn.microsoft.com/fr-fr/express/aa975050.aspx.
Les outils en anglais
Si vous matrisez langlais, prenez soin de choisir les versions anglaises qui sont plus compltes au niveau du support et de la compatibilit. Il est beaucoup plus dlicat dinstaller Silverlight pour Visual Studio dans sa version franaise que dans sa version anglaise.
Si vous dsirez directement utiliser les outils professionnels, tlchargez Visual Studio 2008. Vous pouvez galement tlcharger le Framework 3.5 cette adresse : http://www.microsoft .com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35-B531-508D977D32A6&displaylang=en. Cependant, ce nest pas obligatoire, le Framework 2.0 install par dfaut sur tout les Windows (XP, Vista, Windows Server) est largement suffisant pour crer des applications web. Le 3.5 apportent de nombreuses nouveauts quil nest pas intressant de connatre quand on dbute la programmation web avec ASP.NET.
Premier exemple
Que vous possdiez Visual Web Developer ou Visual Studio, la procdure est la mme. La premire chose faire est de crer un site web. Pour cela, rendez-vous dans le menu File/New/Web Site.
183
Silverlight et ASP.NET
Slectionnez ASP.NET Web Site, donnez-lui un nom et cliquez sur OK. Visual Studio/Web Developer cre pour vous un ensemble de chiers et de dossiers pour vous aider dmarrer. Vous pouvez voir ces chiers dans lExplorateur de solution.
c Fig. 4.2 : Explorateur de solution
Default.aspx est souvent la page par dfaut dun site ASP.NET. Ceci est congurable dans IIS, le programme traitant les demandes sur des pages Internet (qui coute sur le port 80 par exemple). Cest ce que fait Apache si vous tes habitu travailler avec PHP, Ruby, etc. Default.aspx a un chier qui lui est attach. Il est nomm Default.aspx.cs.
184
Introduction ASP.NET
Cest dans ce chier que se trouvera toute la logique mtier de notre page. Microsoft a voulu sparer le design et le code. Vous aurez donc tout laspect graphique au niveau de Default.aspx et tout laspect code au niveau de Default.aspx.cs (on appelle le code contenu dans ce chier le code behind). Ceci nest pas obligatoire, vous pouvez dclarer le design et le code dans un mme chier. Le code se trouvera alors entre des balises script mais cela nuit la lisibilit du code et la comprhension de celui-ci. Default.aspx ressemble ceci lorsque vous louvrez :
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>
Cette page ne fait rien du tout. Si vous voulez obtenir un aperu dans le navigateur, cliquez du bouton droit sur le nom de la page dans lExplorateur de solution et cliquez sur View in browser. Par dfaut, votre navigateur se lance et affiche une page blanche. En fait, le contenu de votre page doit tre situ entre les balises form. Nous reviendrons plus tard sur ces balises. La premire ligne de notre page indique un certain nombre dinformations :
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
185
Silverlight et ASP.NET
Cette ligne est appele une directive. Toutes les directives dune page commencent par <%@ et nissent par %>. Ces directives permettent de dclarer des informations ncessaires au compilateur pour compiler la page. Par exemple, nous avons besoin de savoir quel langage est utilis (Language="C#") pour connatre le compilateur qui traitera la page ou le chier contenant le code (CodeFile="Default.aspx.cs"). Le reste de la page devrait vous tre familier si vous avez lhabitude de programmer des sites Internet. On retrouve une ligne pour le dtd :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Le reste de la page ne devrait pas vous poser de gros problme de comprhension, mis part le form.
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>
186
Introduction ASP.NET
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } }
Code attach
Nous avons chaque fois ce principe de deux chiers. Un pour le code, lautre pour la reprsentation. En effet, en Silverlight on trouve un chier XAML et un chier de code. En ASP.NET, nous avons un chier HTML et un autre chier pour le code. Ce principe est appliqu partout dans les technologies Microsoft.
On remarque directement des usings qui permettent de faciliter lutilisation des composants du Framework .NET. Par exemple, sans using System.IO, vous devriez crire dans votre code :
System.IO.File.Exists("file.txt");
Les usings qui sont par dfaut affichs dpendent du Framework que vous utilisez. Ici, nous avons employ la dernire version de celui-ci (3.5). Ne vous inquitiez pas si vous avez des usings diffrents des miens. Ce qui suit est plus intressant. On voit la dclaration dune classe qui hrite de Page et dclare une mthode Page_Load. Cette mthode est un exemple devent handler. Celle-ci dclenche lvnement Load de notre page ; elle sera excute chaque fois que nous rechargerons la page, Load en anglais signiant Chargement. Il existe de nombreux vnements dclenchs au chargement de la page que nous verrons un peu plus loin.
187
Silverlight et ASP.NET
Outre toutes les balises HTML que vous connaissez, ASP.NET propose de nombreux contrles qui vous simplieront lcriture de vos applications web. Ces derniers commencent tous par <asp :. On trouvera, parmi les plus utiliss :
j j j j
le le le le
Vous trouvez la liste entire de ces contrles dans la toolbox de votre Visual Studio/Web Developer.
c Fig. 4.4 : Barre doutils
Pour insrer lun de ces contrles dans votre page, slectionnez-le dans votre toolbox et dplacez-le sur votre page :
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
188
Introduction ASP.NET
Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text=" Mon premier label"></asp:Label> </div> </form> </body> </html>
Nous avons par exemple ajout un label notre page. Remarquez la proprit runat="server" qui permet dindiquer que ce contrle devra tre valu au niveau du serveur. Si vous lancez la page de votre Explorateur, vous verrez que notre asp :label a t transform en une balise span :
<span id="Label1">Mon premier label</span>
Que sest-il pass ? Le compilateur a vu un contrle qui devait tre interprt par le serveur, celui-ci la trait pour le remplacer par du HTML, comprhensible par le navigateur. Dans ce cas, lutilisation dun contrle ne savre pas utile. Lutilit vient lorsque vous traitez ce contrle dans le code behind. Vous avez en effet la possibilit dditer les proprits du label en code behind (Text, etc.) :
protected void Page_Load(object sender, EventArgs e) { Label1.Text = "Ce label a t trait dans le code behind"; }
189
Silverlight et ASP.NET
Code attach
Ce que vous crivez dans le code behind pour la proprit Text prend le dessus sur ce que vous avez crit dans le design de la page car lvnement Load de la page passe aprs la traitement du render de la page. La proprit de votre label est dans un premier temps gale Mon premier label mais elle est ensuite rcrite au moment du Load.
Le Web.cong
Le Web.cong est un chier que vous retrouvez la racine de votre application et qui contient toutes les informations sur la conguration de celle-ci. Si vous ouvrez le Web.cong de votre application web, vous trouverez une srie dinformations. Parmi les informations importantes :
190
</pages>
191
Silverlight et ASP.NET
RequiredFieldValidator ; RangeValidator ;
192
j j j
193
Silverlight et ASP.NET
Ces quelques lignes vont permettre dafficher une liste de personnes. Eval permet de mapper un lment avec un champ de la base de donnes. Le repeater est comme une boucle qui parcourt tous les lments de la source de donnes passe comme valeur de la proprit DataSourceID. Ici la source de donnes contient les rsultats de la requte SQL passe comme valeur la proprit SelectCommand :
SELECT TOP 3 [PersonneId], [Nom], [Prenom], [Biographie], [Titre] FROM [Personne] WHERE ([PersonneId] = @PersonneId)
On indique que le paramtre doit tre trouv dans lURL de la requte. On va chercher le paramtre id de lURL. Sil nexiste pas, on prend par dfaut la valeur 1. Pour simplier lcriture de ce code, Visual Studio vous fournit un wizard de paramtrage dun DataSource. Pour utiliser ce dernier, rendez-vous en mode Design et cliquez sur la petite icne en haut droite de votre SQLDataSource.
194
Cliquez sur Congure DataSource. Une nouvelle fentre apparat ; vous avez la possibilit de dnir votre chane de connexion votre base de donnes. Cette chane peut tre dnie en cliquant sur New Connection et en remplissant les diffrents champs de connexion (nom du serveur, login, mot de passe, base de donnes). En cliquant sur Suivant, un utilitaire vous permet de crer votre requte.
c Fig. 4.7 : diteur de requtes
Cliquez sur Suivant puis sur Terminer. Votre DataSource est congur. Pour en savoir plus sur SQLDataSource, consultez le lien : http://msdn.microsoft.com/fr-fr/ library/system.web.ui.webcontrols.sqldatasource.aspx.
195
Silverlight et ASP.NET
<asp:TreeNode Text="MSN" NavigateUrl="http://www.msn.com"/> <asp:TreeNode Text="MSNBC News" NavigateUrl="http://www.msnbc.msn.com"/> </asp:TreeNode> </asp:TreeNode> </asp:TreeNode> </Nodes> </asp:TreeView>
On obtient ceci :
c Fig. 4.8 : Vue dun arbre de donnes
Vous pouvez galement mapper le contenu de votre TreeView un chier XML, par exemple. Pour plus dinformation sur les contrles de navigation : http://quickstarts.asp.net/ QuickStartv20/aspnet/doc/ctrlref/navigation/default.aspx.
login dun utilisateur ; affichage du nom de lutilisateur actuellement connect ; enregistrement dun utilisateur ; perte de mots de passe ; changement de mot de passe ; affichage dlments en fonction du statut de lutilisateur (connect, non connect, dans un groupe, ou pas) ; gestion de rles dutilisateur (administrateur, membre, etc.).
Pour permettre lutilisation de ces composants, vous devez rgler ces derniers laide de ladministration centrale de votre site ASP.NET :
c Fig. 4.9 : Centrale dadministration dASP.NET
196
Dans longlet Scurit, vous pouvez choisir dutiliser ASP.NET MemberShip Provider en cliquant sur le lien Slectionnez le type dauthentication. Slectionnez Par internet. Pour plus dinformations sur les composants login, consultez le lien suivant : http:// quickstarts.asp.net/QuickStartv20/aspnet/doc/ctrlref/login/default.aspx.
Vous pouvez alors modier les proprits de ces contrles dans le code behind :
Name.Value = "ici";
Lorsque ASP.NET voit un tag HTML avec la proprit runat, il reconnat un contrle ASP.NET. Par exemple, ici, il sait que linput est un HtmlInputText. Plus dinformations ici : http://quickstarts.asp.net/QuickStartv20/aspnet/doc/ctrlref/html/default.aspx.
Postback et ViewState
Voici une petite introduction ce qui caractrise le modle de programmation ASP.NET. Revenons sur notre exemple de formulaire. Lorsque nous voulons envoyer les informations de notre formulaire, nous devons grer un vnement sur le clic du bouton. Pour cela, nous lui dclarons un handler :
<asp:Button ID="btGo" runat="server" Text="Envoyer" onclick="btGo_Click" />
Lorsque vous cliquez sur le bouton, il y a un Postback ou une requte POST sur la page en cours. Vous devez grer cet vnement dans le code behind sur la mthode btGo _Click :
protected void btGo_Click(object sender, EventArgs e) { // Traitement ici }
En HTML, llment form permet denvoyer une requte POST (ou GET). Si on regarde le code source de notre page, on voit que notre form runat=server sest transform en formulaire :
197
Silverlight et ASP.NET
Laction du formulaire est bien la page actuelle. Le JavaScript est l car il y a des choses vrier aprs lenvoi du formulaire ( cause de notre validator). On remarque galement un champ de type input appel ViewState :
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTcwNjkwMjI1M2QYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja 0tleV9fFgEFDWNiUEx1c0RlMThhbnOWq/eV0Z6qaaIUowq3lP+t4xSruA==" />
Ce champ hidden est gr automatiquement par ASP.NET pour sauvegarder ltat des diffrents contrles de la page. Cest grce cela que lorsque vous effectuez un PostBack, vos informations sont toujours visibles dans le formulaire. Vous navez donc pas besoin de sauver vous-mme ltat des diffrents lments de votre page en ASP.NET.
198
#SilverlightControlHost { height: 100%; } </style> <script type="text/javascript"> function onSilverlightError(sender, args) { var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; } var errorType = args.ErrorType; var iErrorCode = args.ErrorCode; var errMsg = "Unhandled Error in Silverlight 2 Application " + appSource + "\n" ; errMsg += "Code: "+ iErrorCode + " \n"; errMsg += "Category: " + errorType + " \n"; errMsg += "Message: " + args.ErrorMessage + " \n"; if (errorType == "ParserError") { errMsg += "File: " + args.xamlFile + " \n"; errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } errMsg += "MethodName: " + args.methodName + " \n"; } throw new Error(errMsg); } </script> </head> <body> <!-- Les erreurs dexcution Silverlight safficheront ici. Il sagit dinformations de dbogage qui doivent tre supprimes ou masques, une fois le dbogage termin --> <div id=errorLocation style="font-size: small;color: Gray;"></div>
199
Silverlight et ASP.NET
<div id="SilverlightControlHost"> <object data="data:application/x-Silverlight," type="application/x-Silverlight-2" width="100%" height="100%"> <param name="source" value="Mastermind.xap"/> <param name="onerror" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="2.0.31005.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Tlchargez Microsoft Silverlight" style="border-style: none"/> </a> </object> <iframe style=visibility:hidden;height:0;width:0;border:0px></iframe> </div> </body> </html>
Ce nest pas dans la logique de ASP.NET dutiliser des contrles HTML sinitialisant avec JavaScript. Cette page ne ressemble en rien ce que nous avons lhabitude de voir en ASP.NET. La page a perdu beaucoup de lisibilit par rapport ASP.NET.
Dautre part, nous avons vu dans un autre chapitre ce que gnrait Expression Encoder :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd"> <!-- saved from url=(0014)about:internet --> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type=text/javascript src="MicrosoftAjax.js"></script> <script type=text/javascript src="Silverlight.js"></script> <script type=text/javascript src="SilverlightControl.js"></script> <script type=text/javascript src="SilverlightMedia.js"></script> <script type=text/javascript src="ExpressionPlayer.js"></script> <script type=text/javascript src="PlayerStrings.js"></script> <script type=text/javascript src="player.js"></script> <script type=text/javascript src="StartPlayer.js"></script> <title></title> <style type="text/css"> html, body { margin: 0; padding: 0; height:100% }
200
#divPlayer_0 { min-height: 100%; height:100%; } </style> </head> <body style="background-color:black;margin:0,0,0,0;overflow:auto;"> <div id="divPlayer_0"> <script type=text/javascript> var player = new StartPlayer_0(); </script> </div> </body> </html>
Mme chose ici, il est trs rare de voir linsertion de chier JavaScript comme cela dans ASP.NET. Pour remdier aux deux problmes, Microsoft a introduit deux nouveaux contrles dans ASP.NET :
j j
Silverlight ; MediaPlayer.
Le contrle MediaPlayer
Le contrle serveur ASP.NET MediaPlayer vous permet dintgrer des sources de mdia telles que des lments audio (WMA) et vido (WMV) dans une application web, sans quil soit ncessaire de disposer de connaissances en XAML ou en JavaScript. Le contrle MediaPlayer peut utiliser des apparences pr gnres, ou vous pouvez crer des apparences personnalises. Par exemple, vous pouvez rfrencer un document XAML personnalis gnr via Microsoft Expression Encoder et prenant en charge des lgendes, des chapitres et des marqueurs dans la source du mdia. Lorsque vous congurez le contrle MediaPlayer pour rfrencer une apparence pr gnre, le document XAML associ est copi dans le projet. La proprit MediaSkinSource du contrle MediaPlayer est galement congure pour pointer sur lapparence rfrence. Linteraction entre le contrle MediaPlayer et la page peut se faire laide de JavaScript. Ce lecteur ASP.NET sutilise trs facilement. Vous devez rfrencer un chier jouer (par exemple, un chier .wmv, .wma ou .mp3), puis vous slectionnez une apparence intgre. Le contrle serveur MediaPlayer reconnat les formats de mdia pris en charge par le plug-in Silverlight :
<asp:MediaPlayer ID="MediaPlayer1"
201
Silverlight et ASP.NET
runat="server" MediaSource="~/Media/video.wmv" MediaSkinSource="~/MediaSkins/Professional.xaml" ScaleMode="Stretch" AutoLoad="true" AutoPlay="false" PluginBackground="Black" Height="240px" Width="320px"> </asp:MediaPlayer>
Pour fonctionner, le MediaPlayer a besoin dun contrle ASP. NET ScriptManager. Ce contrle permet la gestion des lments JavaScript. Dans une page ASP.NET qui utilise le JavaScript, le ScriptManager charge les scripts JavaScript ncessaires au bon fonctionnement de la page :
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %> <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:MediaPlayer ID="MediaPlayer1" runat="server" Height="240px" Width="320px" MediaSource="~/Lake.wmv"> </asp:MediaPlayer> <br /> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> </div> </form> </body> </html>
202
Si vous excutez ce code et que vous regardiez le code source, vous trouverez normment de JavaScript, notamment pour la cration du lecteur :
<span id="MediaPlayer1_parent"></span> <script type="text/javascript"> //<![CDATA[ Sys.UI.Silverlight.Control.createObject(MediaPlayer1_parent, \u003cobject type="application/x-Silverlight" id="MediaPlayer1" style="height:240px;width:320px;">\r\n\t\u003ca href="http://go2.microsoft.com/fwlink/?LinkID=114576&v=1.0">\u003cimg src="http://go2.microsoft.com/fwlink/?LinkID=108181" alt="Tlchargez Microsoft Silverlight" style="border-width:0;" /> \u003c/a>\r\n\u003c/object>); //]]> </script> c Fig. 4.10 : Lecteur Silverlight
Le contrle MediaPlayer permet de faire exactement la mme chose que ce que vous aviez fait avec Expression Encoder. Il en va de mme pour la gestion des chapitres. Vous pouvez facilement ajouter des chapitres votre vido :
<%@ Page Language="C#" %> <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html > <head id="Head1" runat="server"> <title>ASP.NET Controls for Silverlight</title> <link href="~/SilverlightStyles.css" type="text/css" rel="Stylesheet" /> </head> <body> <form id="form1" runat="server">
203
Silverlight et ASP.NET
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="false" /> <div> <asp:MediaPlayer runat="server" ID="MediaPlayer1" ScaleMode="Stretch" AutoPlay="true" MediaSource="../media/expressionstudio.wmv" Height="480" Width="640" PluginBackground="Black" MediaSkinSource="../skins/Professional.xaml"> <Chapters> <asp:MediaChapter ThumbnailSource="../media/MarkerThumb 00.00.00.jpg" Position="0.0" Title="Chapter 1" /> <asp:MediaChapter ThumbnailSource="../media/MarkerThumb 00.00.10.jpg" Position="10" Title="Chapter 2" /> <asp:MediaChapter ThumbnailSource="../media/MarkerThumb 00.00.24.jpg" Position="24" Title="Chapter 3" /> </Chapters> </asp:MediaPlayer> </div> </form> </body> </html>
Llment Chapters que vous ajoutez permet de dnir des chapitres dans votre vido.
Information en provenance de votre base de donnes
Il se peut que certaines informations proviennent de votre base de donnes comme les chapitres et lemplacement sur chier de votre vido. Dans ce cas, vous pouvez crer un Web service qui expose sous forme XML les donnes de la vido. En effet, avec la proprit MediaDefinition vous pouvez donner lemplacement dun chier XML qui dnit votre vido en respectant le modle suivant : <mediaDefinition> <mediaItems> <mediaItem mediaSource="video.wmv" placeholderSource="image0.jpg"> <chapters> <chapter position="5.00" thumbnailSource="image1.jpg" title="marker1" /> <chapter position="10.00" thumbnailSource="image2.jpg" title="marker2" />
204
Comme indiqu prcdemment dans ce chapitre, vous pouvez interagir avec le lecteur Silverlight via JavaScript.
MediaPlayer et JavaScript
Le JavaScript permet dinteragir de manire pousse avec le lecteur Silverlight. Vous pouvez par exemple crer sur la page dautres boutons qui permettent deffectuer les actions pause ou play. Ces boutons contactent alors une fonction JavaScript connecte au lecteur. On peut aussi mettre jour certains lments de la page, par exemple savoir quand un chapitre change ou quand le statut change. Vous pouvez ainsi dclarer une srie dvnements dans votre lecteur :
<asp:MediaPlayer runat="server" ID="MediaPlayer1" Width="400" Height="300" ScaleMode="Stretch" MediaSource="../media/expressionstudio.wmv" Volume="1.0" PlaceholderSource="../media/placeholder.JPG" OnClientMediaOpened="onMediaOpened" OnClientChapterStarted="onChapterChanged" OnClientMarkerReached="onMarkerReached" OnClientCurrentStateChanged="onStateChanged" OnClientVolumeChanged="onVolumeChanged"> <Chapters> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.00.00.jpg" Position="0.0" Title="Opening credits and movie start." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.00.10.2390000.jpg" Position="10.2390000" Title="Designing and selecting." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.00.24.1360000.jpg" Position="24.1360000" Title="Producing designs." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.00.37.9290000.jpg" Position="37.9290000"
205
Silverlight et ASP.NET
Title="Checking inventory and orders." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.00.52.3490000.jpg" Position="52.3490000" Title="Purchasing." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_MarkerThumb 00.00.58.6180000.jpg" Position="58.6180000" Title="Reviewing." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.01.14.0820000.jpg" Position="74.0820000" Title="End credits." /> <asp:MediaChapter ThumbnailSource="../media/ExpressionStudio_ MarkerThumb 00.01.22.9640000.jpg" Position="82.9640000" Title="Silverlight end." /> </Chapters> </asp:MediaPlayer>
chacun de ces vnements correspond une fonction JavaScript, comme ici dans le changement de chapitre qui modie le contenu HTML dune zone HTML :
function onChapterChanged(sender, args) { // When the chapters change, set the chapter image and text in markup. var chapter = __player.get_currentChapter(); if (chapter === -1) { $get(ChapterImage).src = "../media/placeholder.jpg"; $get(ChapterIndex).innerHTML = "(none)"; } else { $get(ChapterImage).src = __player.get_currentChapter().get_thumbnailSource(); $get(ChapterIndex).innerHTML = "#" + (__player.get_chapterStarted() + 1) + " - " + __player.get_currentChapter().get_title(); $get(MovieTime).innerHTML = __player.get_position(); }
206
Si on veut contrler le lecteur (play, pause, stop), nous pouvons galement le faire en JavaScript :
function onPlay() { __player.play(); $get(pause).disabled = ""; $get(stop).disabled = ""; $get(play).disabled = "disabled"; } function onPause() { __player.pause(); $get(pause).disabled = "disabled"; $get(play).disabled = ""; } function onStop() { __player.stop(); $get(pause).disabled = "disabled"; $get(stop).disabled = "disabled"; $get(play).disabled = ""; }
Cest peu prs tout ce que vous pouvez effectuer avec le contrle MediaPlayer.
Le contrle Silverlight
Grce ce contrle, vous pouvez intgrer du code XAML et tout code de prise en charge (un assembly de code manag, un module de script de langage dynamique manag ou des bibliothques JavaScript client, voir annexe) dans votre site web.
Code manag
Le code manag est un code compil. linverse dun code interprt, le code compil est organis de manire intelligente. Plus dinformation : http://en.wikipedia.org/wiki/Compiler.
Lorsque vous crez un projet Silverlight dans Visual Studio, vous avez directement la possibilit de dnir un projet ASP.NET associ. Ds que cette connexion entre les deux projets est cre, vous voyez apparatre un chier xap dans le dossier ClientBin.
207
Silverlight et ASP.NET
Le contrle Silverlight a besoin de ce chier xap. Cest ce dernier qui va tre interprt.
c Fig. 4.11 : Explorateur de solution
Si vous crez un rectangle en XAML, que vous compiliez votre application ([Ctrl]+[Maj]+[B]) et que vous utilisiez le chier xap dans votre contrle Silverlight, vous obtenez le rsultat escompt :
<UserControl x:Class="SilverlightApplication2.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Rectangle Height="83" Margin="68,50,137,0" VerticalAlignment="Top" Stroke="#FF000000"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF000000"/> <GradientStop Color="#FFA31212" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> </UserControl>
208
<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;"> <head runat="server"> <title>SilverlightApplication2</title> </head> <body style="height:100%;margin:0;"> <form id="form1" runat="server" style="height:100%;"> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <div style="height:100%;"> <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication2.xap" MinimumVersion="2.0.31005.0" Width="100%" Height="100%" /> </div> </form> </body> </html>
Rsultat :
c Fig. 4.12 : Rsultat de notre application
209
Silverlight et ASP.NET
namespace SilverlightApplication2 { public partial class Page : UserControl { public Page() { InitializeComponent(); HtmlElement button = HtmlPage.Document.GetElementById("HTMLButtonA"); if (button != null) button.AttachEvent("onclick", new EventHandler<HtmlEventArgs>( delegate(object o, HtmlEventArgs e) { HtmlButtonClicked("A"); })); button = HtmlPage.Document.GetElementById("HTMLButtonB"); if (button != null) button.AttachEvent("onclick", new EventHandler<HtmlEventArgs>( delegate(object o, HtmlEventArgs e) { HtmlButtonClicked("B");
210
Check-list
})); button = HtmlPage.Document.GetElementById("HTMLButtonC"); if (button != null) button.AttachEvent("onclick", new EventHandler<HtmlEventArgs>( delegate(object o, HtmlEventArgs e) { HtmlButtonClicked("C"); }));
} private void HtmlButtonClicked(string which) { HTMLMessage.Text = "HTML Button " + which + " Clicked"; } } }
On attache trois vnements trois boutons de la page et on affiche quel bouton a t cliqu par la suite. C# permet davoir des interactions bien plus fortes entre le DOM et Silverlight, mais il sagit de concepts avancs qui ne seront pas abords dans ce livre. Pour plus dinformations, rendez-vous sur le site de MSDN (voir Annexe 3, Webographie).
4.5 Check-list
Nous avons tudi dans ce chapitre :
a lensemble des contrles ASP.NET ; a le contrle media pour jouer des vidos Silverlight ; a le contrle Silverlight pour mieux intgrer vos applications dans ASP.NET.
211
5
5.1 Le DataBinding en dtails .............................. 5.2 Les Styles et ControlTemplates ......................... 5.3 Crer un UserControl ................................... 5.4 Les contrles de la librairie System.Windows. Controls .................................................. 5.5 Le contrle DataGrid ................................... 5.6 Les contrles Silverlight Toolkit de CodePlex ......... 5.7 Check-list ................................................. 214 220 225 246 253 269 271
Concepts avancs
D
j
ans ce chapitre, nous allons approfondir les connaissances acquises au chapitre 2, Le langage XAML. Ce chapitre traitera principalement de linteraction humain-machine. Cette interaction peut tre simplie : pour le dveloppeur dune part, DataBinding deux sens, aux ControlTemplates et aux UserControls ; grce au Styles et
Concepts avancs
namespace Filmotheque { public class Film { private string titre; public string Titre { get { return titre; } set { titre = value; } } private string ralisateur; public string Ralisateur { get { return ralisateur; } set { ralisateur = value; } }
214
Le DataBinding en dtails
private int nombreDEtoiles; public int NombreDEtoiles { get { return nombreDEtoiles; } set { nombreDEtoiles = value; } } public Film() { } } }
Au cours de ce chapitre, nous aurons aussi besoin dune collection de lms sur laquelle travailler. Prenons les devants et dclarons-la :
Collection de lms
using using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Collections.Generic;
namespace Filmotheque { public static class CollectionDeFilms { public static List<Film> Films = new List<Film>() { new Film() { Titre="Retour vers le Prsent 7", Ralisateur="Takis Ergopoulos", NombreDEtoiles=5}, new Film() { Titre="Il faut sauver le magicien dOz", Ralisateur="Orhan Benekhol", NombreDEtoiles=1}, new Film() { Titre="La guerre des Chtis",
215
Concepts avancs
Ralisateur="Gautier Lebeaugros", NombreDEtoiles=4}, new Film() { Titre="2009 lodise des Interfaces", Ralisateur="Ilkay Nmtzakis", NombreDEtoiles=3}, new Film() { Titre="Silverlight 2 Ze Movie", Ralisateur="Salvador Bargelot", NombreDEtoiles=4}, }; } }
DataContext
Lattribut DataContext est prsent dans chaque lment dinterface Silverlight. Cest lunit de ce quest la multitude ItemSource dune ListBox. Ainsi, lorsque vous "bindez" lItemSource dune ListBox une liste dobjets, par exemple une liste de lms, chaque item gnr comme enfant de cette ListBox par le DataBinding possdera un DataContext rfrence du Film ayant servi de source sa gnration. Pour simplier, si nous lions par DataBinding la CollectionDeFilms une ListBox :
Une ListBox (XAML)
<UserControl x:Class="Filmothque.Page" ()> <Grid x:Name="LayoutRoot" Background="White"> <ListBox Name="UneListBox"/> </Grid> </UserControl>
216
Le DataBinding en dtails
Chaque lment Filmotheque.Film de la ListBox contient un DataContext pointant vers le lm quil reprsente. Dans le code de la logique applicative, il est alors possible de rcuprer ce lm partir de llment XAML. Qui plus est, un DataContext peut tre rempli par le dveloppeur sur dautres lments quun lment auto-gnr par DataBinding. Par exemple, avec cette interface :
Interface recevant un DataContext cod en dure (Xaml)
<UserControl x:Class="Filmotheque.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <StackPanel x:Name="LayoutRoot" Background="White"> <StackPanel Orientation="Horizontal" Margin="4"> <TextBlock Text="Titre:" Margin="5"/> <TextBlock Text="{Binding Path=Titre}" Margin="5"/> </StackPanel> <StackPanel Orientation="Horizontal" Margin="4"> <TextBlock Text="Ralisateur:" Margin="5"/> <TextBlock Text="{Binding Path=Ralisateur}" Margin="5"/> </StackPanel> <StackPanel Orientation="Horizontal" Margin="4"> <TextBlock Text="Etoiles:" Margin="5"/> <TextBlock Text="{Binding Path=NombreDEtoiles} Margin="5"/> </StackPanel> </StackPanel> </UserControl>
217
Concepts avancs
Cest exactement le mme procd qui est utilis par la plateforme lorsquelle gnre les items dune ListBox partir de DataTemplate. Pour chaque objet prsent dans la collection de donnes en ItemSource, la plateforme ajoute aux enfants de la ListBox une copie du DataTemplate dont le DataContext est lobjet courant.
OneWay ; ce Mode est destin uniquement laffichage de donnes. TwoWay ; ce Mode sert aussi bien laffichage et la modication de donnes.
Le code XAML est-il le seul code modier pour ajouter cette fonctionnalit ? On aimerait bien mais en fait, si modier uniquement le code XAML permet dajouter cette fonctionnalit, malheureusement, les modications apportes aux donnes ne seront pas propages nouveau vers linterface lors dune modication. Dans un cas tel que celui-ci avec des lments daffichage de donnes, linterface ne sera pas mise jour. Cela tant, ce cas reste isol. Usuellement, il est inutile dafficher des donnes dans deux lments dinterface diffrents. Quoi que Pour pallier ce problme, il faut attraper un vnement tel que LostFocus dans le code de la logique applicative et forcer la mise jour du DataContext.
218
Le DataBinding en dtails
219
Concepts avancs
isIntialized = true; LayoutRoot.DataContext = CollectionDeFilms.Films[0]; } private void Input_LostFocus(object sender, RoutedEventArgs e) { ResetDataContext(); } private void ResetDataContext() { if (!isIntialized) return; LayoutRoot.DataContext = null; LayoutRoot.DataContext = CollectionDeFilms.Films[0]; } } }
220
FontWeight="Bold" HorizontalAlignment="Center" Text="TextBlock1"/> <TextBlock Foreground="Black" FontSize="15" FontFamily="Arial" FontWeight="Bold" HorizontalAlignment="Center" Text="TextBlock2"/> <TextBlock Foreground="Black" FontSize="15" FontFamily="Arial" FontWeight="Bold" HorizontalAlignment="Center" Text="TextBlock3"/> <TextBlock Foreground="Black" FontSize="15" FontFamily="Arial" FontWeight="Bold" HorizontalAlignment="Center" Text="TextBlock4"/> </StackPanel> </UserControl>
221
Concepts avancs
Le code devient bien plus lisible et on peut en assurer facilement la maintenance. Changer globalement laspect des TextBlock du Style BoldTextBlock se fait en une modication au lieu de quatre. Le rsultat, quant lui, reste le mme :
c Fig. 5.3 : TextBlock avec Style
Un style possde comme attributs une x:Key le reprsentant et un TargetType. Le TargetType est le type dlment XAML auquel le style peut tre appliqu. Laisser vide cette dernire proprit vous permettra dappliquer ce style nimporte quel lment XAML. En contrepartie, il est dangereux de sy rsoudre par simplicit vu que certains attributs (tels que Foreground) ne sont pas partags par tous les lments XAML. Les lments enfants des styles sont les setters. Un setter congure lattribut du nom de Property avec la valeur Value.
ControlTemplate
Un ControlTemplate est une sorte de style qui, au lieu de congurer certains attributs dun lment dinterface, remplace compltement son affichage par un arbre XAML :
Exemple de ControlTemplate
<UserControl x:Class="Filmotheque.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="150" Height="150"> <StackPanel x:Name="LayoutRoot" Background="White"> <StackPanel.Resources> <Style x:Key="BoldTextBlockStyle" TargetType="TextBlock"> <Setter Property="Foreground" Value="Black"/> <Setter Property="FontSize" Value="15"/> <Setter Property="FontFamily" Value="Arial"/> <Setter Property="FontWeight" Value="Bold"/> <Setter Property="HorizontalAlignment" Value="Center"/> </Style> <ControlTemplate x:Key="ActionControlTemplate" TargetType="Button"> <Border Background="Silver"
222
BorderThickness="2" BorderBrush="Blue" CornerRadius="0,0,15,0" Margin="5"> <StackPanel Orientation="Vertical" Margin="5"> <TextBlock Style="{StaticResource BoldTextBlockStyle}" Text="{TemplateBinding Content}" HorizontalAlignment="Left"/> <Button Click="{TemplateBinding Click}"> <TextBlock Style="{StaticResource BoldTextBlockStyle}" HorizontalAlignment="Right" Text="Do it!"/> </Button> </StackPanel> </Border> </ControlTemplate> </StackPanel.Resources> <Button Template="{StaticResource ActionControlTemplate}" Content="Une Action"/> <Button Template="{StaticResource ActionControlTemplate}" Content="Autre Action"/> </StackPanel> </UserControl> c Fig. 5.4 : Exemple de ControlTemplate
trangement, assigner un ControlTemplate un lment XAML ne se fait pas par lattribut ControlTemplate mais via lattribut Template. lintrieur mme du ControlTemplate, un nouveau type de binding montre son nez : le TemplateBinding. Un TemplateBinding permet un ControlTemplate de rcuprer la valeur dun des attributs de llment quil utilise.
223
Concepts avancs
Ainsi en crivant Text="{TemplateBinding Content}", nous allons rechercher le Content des deux boutons qui utilisent ActionControlTemplate. Ceci est dangereux. En effet, nous avons assign par TemplateBinding lattribut Text dune TextBox une valeur qui peut ne pas tre du texte. Rappelons-nous quun Button peut contenir nimporte quel autre lment XAML, ce qui nest pas le cas de lattribut Text, qui lui, accepte uniquement du texte. Pour pallier ce risque, il est prfrable dutiliser un ContentPresenter.Un ContentPresenter est un lment XAML qui possde la capacit dafficher son contenu. Modions le code du ControlTemplate :
ControlTemplate avec ContentTemplate
<UserControl x:Class="Filmotheque.Page" (...) <ControlTemplate x:Key="ActionControlTemplate" TargetType="Button"> <Border Background="Silver" BorderThickness="2" BorderBrush="Blue" CornerRadius="0,0,15,0" Margin="5"> <StackPanel Orientation="Vertical" Margin="5"> <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Left"/> <Button Click="{TemplateBinding Click}"> <TextBlock Style="{StaticResource BoldTextBlockStyle}" HorizontalAlignment="Right" Text="Do it!"/> </Button> </StackPanel> </Border> </ControlTemplate> </StackPanel.Resources> <Button Template="{StaticResource ActionControlTemplate}" Content="Une Action"/> <Button Template="{StaticResource ActionControlTemplate}"> <StackPanel>
224
Crer un UserControl
<TextBlock Text="Ecrire un livre"/> <TextBlock Text="Publier un livre"/> </StackPanel> </Button> </StackPanel> </UserControl> c Fig. 5.5 : ControlTemplate avec ContentTemplate
Dans ce nouvel exemple, que le contenu du bouton soit un simple texte ou un arbre XAML complexe, le rsultat est le mme.
ajouter ses codes XAML et C# la solution Silverlight ; dnir linterface XAML ; crire la logique applicative.
Si le UserControl est dni dans une autre assembly, sassurer quelle a t compile pour Silverlight et en ajouter la rfrence au projet Silverlight. Ajouter lapplication lespace de noms (namespace) contenant lUserControl.
225
Concepts avancs
UserControl ClickMe
Pour apprhender facilement ce concept de contrle utilisateur, nous allons en crire un basique. Cet UserControl contiendra un bouton et changera le contenu de ce bouton lorsquon cliquera dessus. Voici linterface de ClickMe :
ClickMe.xaml
<UserControl x:Class="Filmotheque.ClickMe" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="LayoutRoot" Background="White"> <Button Name="ClickMeButton" Content="Click Me!" Click="Button_Click"/> </Grid> </UserControl>
namespace Filmotheque { public partial class ClickMe : UserControl { public ClickMe() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e)
226
Crer un UserControl
{ ClickMeButton.Content = "Merci"; } } }
UserControl Ranking
Dans loptique de lapplication de gestion de lms, un UserControl permettant dattribuer un nombre dtoiles un lm de manire visuel peut avoir son importance. Le rsultat nal auquel nous aimerions arriver est le suivant :
c Fig. 5.7 : Ranking UserControl
227
Concepts avancs
Un point reste voir avant darriver ce rsultat : Comment ajouter un UserControl une proprit pouvant servir dattributs dans le code XAML.
Les DependencyProperties
Une DependencyProperty est une proprit dclare dans le code applicatif dun UserControl grce la mthode Register de la classe DependencyProperty. Cest une proprit qui au lieu dtre enregistre dans une variable prive du code applicatif, est enregistre par le Framework lui-mme dune manire qui importe peu. Quoi quil en soit, seuls les DependencyProperties sont stables lorsque vous dsirez utiliser un attribut dans le code XAML. Lutilisation dune proprit publique du code applicatif dans ce but peut avoir des effets malencontreux et imprvisibles. Lemploi dune DependencyProperty la place dune proprit publique active la gestion des Animations, des Styles, des Templates et du binding sur cette proprit. Dclaration dune DependencyProperty :
public int MyProperty { get { return (int)GetValue(MyPropertyProperty); } set { SetValue(MyPropertyProperty, value); } }
228
Crer un UserControl
le nom de la proprit ; son type ; le type de sa classe mre, la classe qui te cette DependencyProperty (gnralement la classe dans laquelle cette proprit est dclare) ; une instance de la classe PropertyMetadata spciant la valeur initiale de la proprit.
une proprit du nom MyProperty ; de type nombre entier (int) ; dont la classe hte est ownerclass ; de valeur initiale 0.
Le premier du nom de Star tant une toile unique, capable de varier de couleur (jaune ou gris) quand on clique dessus ou lors de lappel dune de ses fonctions publiques. Le deuxime du nom de Ranking sera un conteneur de cinq UserControl Star, coordonnant leurs travaux.
Star
Pour crer lUserControl Star, nous allons partir dune CheckBox. En effet, comme nous lavons vu au chapitre 2, Le langage XAML, une CheckBox possde un attribut IsChecked deux tats. Cet attribut nous sera utile pour savoir si ltoile est jaune (IsChecked=True) ou si ltoile est grise (IsChecked=False).
229
Concepts avancs
Nous allons ensuite en rednir le ControlTemplate pour lui donner lapparence dune toile. Dans le code suivant, vous dcouvrirez lutilisation de llment gomtrique Path. Cet lment prend comme valeur de lattribut Data une srie de points reprsents par des coordonnes gomtriques. Lattribut Fill de ce Path est li par TemplateBinding au Background de la CheckBox. Cest en faisant varier ce Background de YellowStarBrush GreyStarBrush dans le code applicatif que nous changerons le visuel de ltoile :
Star.xaml
<UserControl x:Class="Filmotheque.Star" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.Resources> <SolidColorBrush x:Key="YellowStarBrush" Color="#FFFF00"/> <SolidColorBrush x:Key="GreyStarBrush" Color="#C0C0C0"/> <Style x:Key="EmptyStarStyle" TargetType="CheckBox"> <Setter Property="Height" Value="40"/> <Setter Property="Width" Value="40"/> <Setter Property="Margin" Value="2"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate x:Name="EmptyStarTemplate"> <Canvas> <Canvas Canvas.Left="5" Canvas.Top="15"> <Path Stroke="#000080" Fill="{TemplateBinding Background}" MouseLeftButtonDown="Path_MouseLeftButtonDown" MouseEnter="Path_MouseEnter" MouseLeave="Path_MouseLeave" StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="M 0,0 l 10,0 l 5,-10 l 5,10 l 10,0 l -7,10 l 2,10 l -10,-5 l -10,5 l 2,-10 Z"/> </Canvas> </Canvas> </ControlTemplate>
230
Crer un UserControl
</Setter.Value> </Setter> </Style> </Grid.Resources> <CheckBox Name="Star1" IsChecked="True" Style="{StaticResource EmptyStarStyle}" Background="{StaticResource YellowStarBrush}"/> </Grid> </UserControl>
MouseLeftButtonDown lorsque lutilisateur cliquera sur ltoile, son attribut IsChecked sera invers. j MouseEnter et MouseLeave lorsque la souris de lutilisateur se trouve au-dessus de ltoile, nous en changerons le Background en Orange.
j
Star.cs
using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace Filmotheque { public partial class Star : UserControl { public event EventHandler OnColorChanged; public bool? IsChecked { get { return (bool?)GetValue(IsCheckedProperty); }
231
Concepts avancs
set { SetValue(IsCheckedProperty, value); Star1.IsChecked = value; SetBackground(); } } public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register( "IsChecked", typeof(bool?), typeof(Star), new PropertyMetadata(true));
public Star() { InitializeComponent(); SetBackground(); } private void Path_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Star1.IsChecked = !Star1.IsChecked; SetBackground(); if (OnColorChanged != null) OnColorChanged(this,EventArgs.Empty); } private void SetBackground() { if (Star1.IsChecked.HasValue && Star1.IsChecked.Value) Star1.Background = (SolidColorBrush) LayoutRoot.Resources["YellowStarBrush"]; else Star1.Background = (SolidColorBrush) LayoutRoot.Resources["GreyStarBrush"]; } #region MouseOverManagement private Brush SolideStateBackground; private void Path_MouseEnter(object sender, MouseEventArgs e) { SolideStateBackground = Star1.Background; Star1.Background = new SolidColorBrush(Colors.Orange);
232
Crer un UserControl
Un point est mettre en vidence dans ce code applicatif : lvnement OnColorChanged qui prviendra lUserControl Ranking que lutilisateur a cliqu sur ltoile.
Ranking
Interface de lUserControl Ranking :
Ranking.xaml
<UserControl x:Class="Filmotheque.Ranking" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:Filmotheque" Width="Auto" Height="Auto" Margin="2" > <Grid x:Name="LayoutRoot" Background="White"> <Border HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" CornerRadius="5" BorderBrush="#000080" BorderThickness="4"> <StackPanel Name="RankingPanel" Orientation="Horizontal"> <MyApp:Star Name="Star1"/> <MyApp:Star Name="Star2"/> <MyApp:Star Name="Star3"/> <MyApp:Star Name="Star4"/> <MyApp:Star Name="Star5"/> </StackPanel> </Border> </Grid> </UserControl>
Comme prvu, du ct de linterface du contrle utilisateur Ranking, il sagit seulement dune collection de contrle utilisateur Star.
233
Concepts avancs
On comprend ici lutilit davoir cr un contrle utilisateur pour les toiles ; il est devenu trs ais de faire varier le nombre dtoiles quun Ranking possde. Qui plus est, pour aller plus loin, il est possible de faire de ce nombre dtoiles maximal une DependencyProperty congurable. Le code applicatif de Ranking va devoir rester lcoute des clics de lutilisateur sur chaque toile et stocker en mmoire le nombre dtoiles qui lui est attribu. En effet, lorsque lutilisateur clique sur ltoile 3, toutes les toiles prcdentes doivent passer ltat jaune et inversement, toutes les toiles suivantes doivent passer ltat gris.
Ranking.cs
using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace Filmotheque { public partial class Ranking : UserControl { public int NombreDEtoiles { get { return (int)GetValue(NombreDEtoilesProperty); } set { SetValue(NombreDEtoilesProperty, value); SetRanking(value); } } public static readonly DependencyProperty NombreDEtoilesProperty =
234
Crer un UserControl
DependencyProperty.Register("NombreDEtoiles", typeof(int), typeof(Ranking), new PropertyMetadata(0)); public Ranking() { InitializeComponent(); foreach(Star star in RankingPanel.Children) star.OnColorChanged += new EventHandler(star_OnColorChanged); } void star_OnColorChanged(object sender, EventArgs e) { Star star = (sender as Star); int Position = int.Parse(star.Name.Replace("Star", "")); SetRanking(Position); } public void SetRanking(int NombreDEtoiles) { for (int i = 1; i <= 5; i++) { Star star = (RankingPanel.FindName("Star" + i) as Star); star.IsChecked = (i <= NombreDEtoiles); } } } }
235
Concepts avancs
xmlns:MyApp="clr-namespace:Filmotheque" Width="400" Height="300"> <StackPanel x:Name="LayoutRoot" Background="White"> <MyApp:Ranking NombreDEtoile="3"/> <MyApp:Ranking NombreDEtoile="{Binding Path=NomberDEtoile, Mode=TwoWay}"/> </StackPanel> </UserControl>
Code applicatif
using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace Filmotheque { public partial class Page : UserControl { public Page() { InitializeComponent(); LayoutRoot.DataContext = CollectionDeFilms.Films[0]; } } }
236
Crer un UserControl
MediaElement
Dans une optique totalement diffrente, nous allons maintenant nous pencher sur un contrle Silverlight des plus puissants : le contrle MediaElement. Le contrle MediaElement permet dafficher et dinteragir avec une vido lintrieur dune application Silverlight.
Attribut MediaElement.Source en XAML bug
Lorsque vous ajoutez un contrle MediaElement votre application Silverlight, nen congurez pas la source partir du code XAML, vous recevrez dans ce cas une erreur de chargement de la vido (Erreur 4001). Ceci est un bogue ouvert chez Microsoft mais restons calme, ce bogue nest pas bloquant, il suffit de congurer la source des MediaElement partir du code applicatif.
237
Concepts avancs
<TextBlock Foreground="White" VerticalAlignment="Center" Margin="5" >Volume</TextBlock> <Slider Name="VolumeSlider" VerticalAlignment="Center" Minimum="0" Maximum="1" Value="0.5" Width="70" ValueChanged="VolumeSlider_ValueChanged"/> <ToggleButton Name="MuteToggleButton" Content="Mute" Margin="5" IsChecked="False" Checked="Mute" Unchecked="UnMute"/> </StackPanel> <Border Background="Black" BorderBrush="WhiteSmoke" BorderThickness="3" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5" CornerRadius="5"> <MediaElement Name="myMediaElement" Width="320" Height="240" Margin="5" Stretch="Fill" AutoPlay="False" MediaFailed="MediaElement_MediaFailed"/> </Border> </StackPanel> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Foreground="White" Margin="5" Grid.Column="0" VerticalAlignment="Center">Seek To</TextBlock> <Slider Name="TimeLineSlider" Margin="5" Minimum="0" Grid.Column="1"/> <TextBlock Name="TimeLineTextBlock" Grid.Column="2"
238
Crer un UserControl
Text="00:00:00/00:00:00" Foreground="White" Margin="5"/> </Grid> </StackPanel> </UserControl> c Fig. 5.12 : Exemple de MediaElement
Dans cette application Silverlight, vous retrouvez un MediaElement et quelques autres contrles destins interagir avec lui. Les diffrents contrles ajouts parlent deux-mmes, le bouton Play sert dmarrer la vido, le bouton Pause larrter temporairement, etc. Le code applicatif, quant lui, cache quelques subtilits :
Code applicatif de lexemple de MediaElement
using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Windows.Data; System.Threading;
namespace Filmotheque {
239
Concepts avancs
public partial class Page : UserControl { public Page() { InitializeComponent(); myMediaElement.Source = new Uri(@"media/Lake.wmv", UriKind.Relative); } private void MediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e) { } private void Play_Click(object sender, RoutedEventArgs e) { TimeLineSlider.Maximum = myMediaElement.NaturalDuration.TimeSpan.TotalSeconds; TimeLineSlider.Value = myMediaElement.Position.TotalSeconds;
myMediaElement.Play(); Timer T = new Timer(new TimerCallback(delegate { Dispatcher.BeginInvoke(new Action(delegate { TimeLineSlider.SetValue(Slider.ValueProperty, myMediaElement.Position.TotalSeconds); TimeLineTextBlock.Text = myMediaElement.Position.Hours + ":" + myMediaElement.Position.Minutes + ":" + myMediaElement.Position.Seconds + "/" + myMediaElement.NaturalDuration.TimeSpan.Hours + ":" + myMediaElement.NaturalDuration.TimeSpan.Minutes + ":" + myMediaElement.NaturalDuration.TimeSpan.Seconds; })); })); T.Change(0, 1000); }
240
Crer un UserControl
private void Pause_Click(object sender, RoutedEventArgs e) { myMediaElement.Pause(); } private void Stop_Click(object sender, RoutedEventArgs e) { myMediaElement.Stop(); } private void VolumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { if (VolumeSlider != null && myMediaElement != null) myMediaElement.Volume = VolumeSlider.Value; } private void Mute(object sender, RoutedEventArgs e) { myMediaElement.IsMuted = true; } private void UnMute(object sender, RoutedEventArgs e) { myMediaElement.IsMuted = false; }
} }
Pour pallier le bogue relatif lattribut Source des MediaElement, cest dans ce code applicatif que lon se doit de lassigner.
c Fig. 5.13 : Exemple de MediaElement en fonctionnement
241
Concepts avancs
Pour faire varier lattribut Valeur du Silder TimeLineSlider, nous avons utilis un objet de la plateforme .Net du nom de Dispatcher.
Dispatcher
Dans une application Silverlight, comme dans une application WPF, linterface est proprit dun unique thread. Cest dans ce thread que sexcutent les diffrents vnements. Cependant, il est parfois ncessaire dattaquer linterface partir dun autre thread. Cest impossible. Le Dispatcher est un objet grant lordre dappel des fonctions du thread de linterface. Tout ce quil est possible de faire partir dun autre thread est de demander au Dispatcher de mettre en queue lappel dune fonction. Quand le Dispatcher en trouvera le temps, il lexcutera. Cette demande se fait partir de la mthode BeginInvoke du Dispatcher :
Utilisation du Dispatcher
Thread autre que le thread interface { /* interaction code interface impossible */ Dispatcher.BeginInvoke(new Action(delegate { /* interaction code interface possible */ })); }
242
Crer un UserControl
Lobjet App.Current.Host.Content contient deux autres proprits qui vont nous servir :
ActualHeight est la hauteur de lcran de lutilisateur. j ActuelWith est la largeur de lcran de lutilisateur.
j
Cet objet contient aussi un vnement : FullScreenChanged sur lequel nous ajouterons une mthode rorganisant la structure de lapplication. Ajout dun bouton FullScreen linterface et modication du code XAML :
MediaElement FullScreen (Xaml)
<UserControl x:Class="Filmotheque.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyApp="clr-namespace:Filmotheque" Width="Auto" Height="Auto"> <StackPanel x:Name="LayoutRoot" Background="Black"> <StackPanel Orientation="Horizontal"> <StackPanel HorizontalAlignment="Center" Name="ButtonStackPanel" VerticalAlignment="Center"> <Button <Button <Button <Button Content="Play" Margin="5" Click="Play_Click"/> Content="Pause" Margin="5" Click="Pause_Click"/> Content="Stop" Margin="5" Click="Stop_Click"/> Content="FullScreen" Margin="5" Click="FullScreen_Click"/>
<TextBlock Foreground="White" VerticalAlignment="Center" Margin="5" >Volume</TextBlock> <Slider Name="VolumeSlider" VerticalAlignment="Center" Minimum="0" Maximum="1" Value="0.5" Width="70" ValueChanged="VolumeSlider_ValueChanged"/> <ToggleButton Name="MuteToggleButton" Content="Mute" Margin="5" IsChecked="False" Checked="Mute" Unchecked="UnMute"/> </StackPanel> <Border Name="EcranBorder" Background="Black" BorderBrush="WhiteSmoke" BorderThickness="3"
243
Concepts avancs
HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5" Width="330" Height="250" CornerRadius="5"> <MediaElement Name="myMediaElement" Margin="5" Stretch="Fill" AutoPlay="False" MediaFailed="MediaElement_MediaFailed"/> </Border> </StackPanel> <Grid Name="SliderGrid" Width="400" HorizontalAlignment="Left"> </StackPanel> </UserControl>
Assigner les attributs Visible des lments ButtonStackPanel et SliderGrid Collapsed. La valeur Collapsed de cet attribut signie que les lments ne doivent ni tre affichs sur linterface, ni occuper la moindre place rsiduelle dans linterface. Redimensionner le Border EcranBorder pour quil occupe toute la place disponible sur lcran de lutilisateur.
244
Crer un UserControl
{ ButtonStackPanel.Visibility = Visibility.Visible; SliderGrid.Visibility = Visibility.Visible; EcranBorder.SetValue(Border.HeightProperty, (double)250); EcranBorder.SetValue(Border.WidthProperty, (double)330); } else { ButtonStackPanel.Visibility = Visibility.Collapsed; SliderGrid.Visibility = Visibility.Collapsed; EcranBorder.SetValue(Border.HeightProperty, App.Current.Host.Content.ActualHeight - 10); EcranBorder.SetValue(Border.WidthProperty, App.Current.Host.Content.ActualWidth 10); } } private void FullScreen_Click(object sender, RoutedEventArgs e) { App.Current.Host.Content.IsFullScreen = true; } c Fig. 5.14 : MediaElement modi pour supporter le FullScreen
245
Concepts avancs
246
Dans la bote de dialogue Ajouter une rfrence, slectionnez longlet .Net. 4 Slectionnez System.Windows.Controls.
3 c Fig. 5.17 : Bote de dialogue Ajouter une rfrence
Cliquez sur OK
Calendar
Le premier de ces contrles utilisateur est un calendrier :
Exemple de Calendar
<UserControl x:Class="TestWindowsControls.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls"
247
Concepts avancs
xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" Width="Auto" Height="Auto"> <Grid x:Name="LayoutRoot" Background="White"> <controls:Calendar Name="calendar"/> </Grid> </UserControl> c Fig. 5.18 : Exemple de Calendar
- Decade affiche 10 annes lutilisateur. - Year affiche 12 mois lutilisateur. - Mounth affiche un mois lutilisateur sous forme de tableau de jours.
j
DisplayDateStart et DisplayDateEnd permettent dafficher seulement une certaine priode de temps sur le calendrier.
Par exemple, pour afficher uniquement les 4 jours de chaque ct du 29 juillet 1985, il faut modier le code applicatif de lapplication :
Exemple de Calendar 2
using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
248
using Filmotheque; namespace TestWindowsControls { public partial class Page : UserControl { public Page() { InitializeComponent(); DateTime Lundi29Juillet85 = new DateTime(1985, 7, 29); calendar.DisplayDate = Lundi29Juillet85; calendar.DisplayDateStart = Lundi29Juillet85.AddDays(-4); calendar.DisplayDateEnd = Lundi29Juillet85.AddDays(4); } } } c Fig. 5.19 : Calendar de 8 jours
DatePicker
Le DatePicker fonctionne majoritairement de la mme faon que le Calendar. Il accepte lui aussi les attributs DisplayDate, DisplayDateStart et DisplayDateEnd. Lattribut DisplayMode y est par contre absent. La vue est xe sur un DisplayMode gal Month. Le DatePicker est un contrle de saisie dinformations, il demande lutilisateur de choisir une date. Lvnement SelectedDateChanged est dclench lorsque lutilisateur a ni sa slection. Cest dans lattribut SelectedDate que le dveloppeur retrouvera le DateTime choisi :
Exemple de DatePicker (Xaml)
<UserControl x:Class="TestWindowsControls.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
249
Concepts avancs
xmlns:controls="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls" xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" Width="Auto" Height="Auto"> <Grid x:Name="LayoutRoot" Background="White"> <controls:DatePicker Name="calendar" HorizontalAlignment="Center" VerticalAlignment="Center" SelectedDateChanged="DatePicker_SelectedDateChanged"/> </Grid> </UserControl> c Fig. 5.20 : Exemple de DatePicker
namespace TestWindowsControls { public partial class Page : UserControl { public Page() { InitializeComponent();
250
DateTime Lundi29Juillet85 = new DateTime(1985, 7, 29); calendar.DisplayDate = Lundi29Juillet85; calendar.DisplayDateStart = Lundi29Juillet85.AddDays(-4); calendar.DisplayDateEnd = Lundi29Juillet85.AddDays(4); } private void DatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e) { if((sender as DatePicker).SelectedDate.HasValue) DateTime choix = (sender as DatePicker).SelectedDate.Value; } } }
GridSplitter
Un GridSplitter est un contrle utilisateur permettant de redimensionner les tailles des colonnes et des lignes dune grille :
Exemple de GridSplitter
<UserControl x:Class="TestWindowsControls.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls" xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" Width="250" Height="250"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Rectangle <Rectangle <Rectangle <Rectangle Grid.Row="0" Grid.Row="0" Grid.Row="1" Grid.Row="1" Grid.Column="0" Grid.Column="1" Grid.Column="0" Grid.Column="1" Fill="Red"/> Fill="Black"/> Fill="Black"/> Fill="Red"/>
251
Concepts avancs
TabControl et TabItem
Un TabControl est un lment de la famille des Layout, il permet donc de structurer linterface. Ses enfants doivent obligatoirement tre des TabItem. Chaque TabItem est alors class dans le TabControl comme on classerait des feuilles dans un range document. Lattribut Header des TabItem permet de prciser le titre. Seul un TabItem peut tre slectionn (donc affich) simultanment. Lors dun clic sur le header dun TabItem, ce TabItem va directement tre slectionn. Les vnements SelectionChanged du TabControl et IsSelectedChanged des TabItems permettent toutefois dagir sur cette fonctionnalit dans le code applicatif :
Exemple de TabControl
<UserControl x:Class="TestWindowsControls.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls" xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" Width="250" Height="250"> <Grid x:Name="LayoutRoot" Background="White"> <controls:TabControl Name="MainTabControl">
252
Le contrle DataGrid
<controls:TabItem Header="StartPage"> <StackPanel> <TextBlock Text="Exemple de TabControl"/> </StackPanel> </controls:TabItem> <controls:TabItem Header="TabItem2" IsSelected="True"> <StackPanel> <Ellipse Fill="Blue" Height="50" Width="70"/> </StackPanel> </controls:TabItem> <controls:TabItem Header="TabItem3"> </controls:TabItem> </controls:TabControl> </Grid> </UserControl>
253
Concepts avancs
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls" xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" Width="600" Height="200"> <Grid x:Name="LayoutRoot" Background="White"> <data:DataGrid Name="dataGrid" HeadersVisibility="All" ColumnWidth="150" RowHeight="20" AutoGenerateColumns="True" RowBackground="Beige" IsReadOnly="False" AlternatingRowBackground="LemonChiffon"> </data:DataGrid> </Grid> </UserControl>
- All. Tous les headers sont visible. - Column. Seuls les titres de colonnes sont visibles. - None. Aucun des headers nest visible. - Row. Seul le header de slection de ligne est visible.
j j
fond des lignes entre chaque item IsReadOnly spcie si les lments de chaque cellule auto gnre sont des lments daffichage ou de saisie dinformations :
Exemple de DataGrid (C#)
254
Le contrle DataGrid
using System.Windows.Media.Animation; using System.Windows.Shapes; using Filmotheque; namespace TestWindowsControls { public partial class Page : UserControl { public Page() { InitializeComponent(); dataGrid.ItemsSource = CollectionDeFilms.Films; } } }
DataGridTextColumn. Il sagit du type de colonnes les plus communes. Elles utilisent un TextBlock pour afficher des donnes et une TextBox pour les diter. DataGridCheckBoxColumn. Ce type de colonne affiche une CheckBox. Comme son nom lindique, lattribut IsEditable de la DataGrid mre de cette colonne est li lattribut IsEditable de la CheckBox. DataGridTemplateColumn. Il sagit du type de colonne par excellence. Il reprend le principe de DataTemplate et il est donc totalement versatile.
255
Concepts avancs
256
Le contrle DataGrid
Remarquez dors et dj la subtile diffrence dans le titre de la colonne reprsentant le nombre dtoiles. Ayant la main sur le contenu de son Header, il nous a t possible de le faire passer de NombreDEtoile Nombre dtoiles.
DataGridCheckBoxColumn et DataGridTemplateColumn
Pour aller plus loin dans les exemples, nous devrons changer de collection de donnes. En effet, une collection de donnes contient uniquement des chanes de caractres et un nombre ne suffit pas exploiter la puissance des DataGridTemplateColumn. Le cas dtude parfait est une liste de projets. Un projet est dni par son nom, sa date de dpart, sa date butoir, sa liste demploys. Un employ est dni par son nom, son prnom, sa date de naissance, sa photo didentit, son adresse de blog et son email. Voici le code des sources de donnes :
Projet.cs
using using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Collections.Generic;
namespace TestWindowsControls { public class Projet { private string nom; public string Nom { get { return nom; } set { nom = value; } } private DateTime dpart;
257
Concepts avancs
public DateTime Dpart { get { return dpart; } set { dpart = value; } } private DateTime buttoir; public DateTime Buttoir { get { return buttoir; } set { buttoir = value; } } private List<Employ> quipe; public List<Employ> Equipe { get { return quipe; } set { quipe = value; } } public Projet() { } } }
Employ.cs
using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes;
namespace TestWindowsControls { public class Employ { private string nom; public string Nom
258
Le contrle DataGrid
{ get { return nom; } set { nom = value; } } private string prenom; public string Prenom { get { return prenom; } set { prenom = value; } } private Uri photo; public Uri Photo { get { return photo; } set { photo = value; } } private Uri blog; public Uri Blog { get { return blog; } set { blog = value; } } private string email; public string Email { get { return email; } set { email = value; } } public Employ() { } } }
CollectionDeProjet.cs
using System; using System.Net; using System.Windows;
259
Concepts avancs
namespace TestWindowsControls { public static class CollectionDeProjet { public static List<Projet> Projets = new List<Projet>() { new Projet() { Nom="OpenApp", Dpart=new DateTime(2009,1,12), Buttoir=new DateTime(2009,2,15), Equipe = new List<Employ>() { CollectionDeProjet.Simon, CollectionDeProjet.Caroline } }, new Projet() { Nom="Livre SL2", Dpart=new DateTime(2006,8,5), Buttoir=new DateTime(2000,1,10), Equipe = new List<Employ>() { CollectionDeProjet.Loc, CollectionDeProjet.Simon } }, new Projet() { Nom="Jubbeo", Dpart=new DateTime(2009,3,6), Buttoir=new DateTime(2009,8,21), Equipe = new List<Employ>() { CollectionDeProjet.Florent,
260
Le contrle DataGrid
CollectionDeProjet.Simon, CollectionDeProjet.Loc } }, new Projet() { Nom="Wipus", Dpart=new DateTime(2006,7,1), Buttoir=new DateTime(2009,4,8), Equipe = new List<Employ>() { CollectionDeProjet.Simon, CollectionDeProjet.Loc, CollectionDeProjet.X } } }; public static Employ Loc = new Employ() { Nom = "Loc", Prenom = "Bar", Email = "loic.bar@wipus.com", Photo = new Uri("Employe/Loic.jpg", UriKind.Relative), Blog = new Uri("http://www.loicbar.com",UriKind.Absolute) }; public static Employ Simon = new Employ() { Nom = "Simon", Prenom = "Boigelot", Email = "simon.boigelot@wipus.com", Photo = new Uri("Employe/Simon.jpg", UriKind.Relative), Blog = new Uri("http://www.simonboigelot.com", UriKind.Absolute) }; public static Employ Florent = new Employ() { Nom = "Florent", Prenom = "G.", Email = "MisterFlo@provider.com", Photo = new Uri("Employe/Buddy.JPG", UriKind.Relative), Blog = new Uri("http://fake.MisterFlo.com", UriKind.Absolute) };
261
Concepts avancs
public static Employ Caroline = new Employ() { Nom = "Caroline", Prenom = "L.", Email = "caroline@wipus.com", Photo = new Uri("Employe/Buddy.JPG", UriKind.Relative), Blog = new Uri("http://fake.KRO.com", UriKind.Absolute) }; public static Employ X = new Employ() { Nom = "", Prenom = "X", Email = "x@wipus.com", Photo = new Uri("Employe/Buddy.JPG", UriKind.Relative), Blog = new Uri("http://fake.X.com", UriKind.Absolute) }; } }
En guise dillustration du problme d lauto gnration, voici ce que donnerait une DataGrid auto gnre dont litemsSource est CollectionDeProjet.Projets.
Les dates reprsentes dans cette DataGrid ont un aspect la limite de lillisible. Quant la liste demploys, impossible de savoir ce quelle contient. Reproduisons dabord ce rsultat :
Reproduction du rsultat auto gnr
<UserControl x:Class="TestWindowsControls.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls" xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data"
262
Le contrle DataGrid
Width="Auto" Height="Auto"> <Grid x:Name="LayoutRoot" Background="White"> <data:DataGrid Name="dataGrid" HeadersVisibility="All" ColumnWidth="150" RowHeight="20" AutoGenerateColumns="False" RowBackground="Beige" IsReadOnly="False" AlternatingRowBackground="LemonChiffon"> <data:DataGrid.Columns> <data:DataGridTextColumn Header="Nom du Projet" Binding="{Binding Path=Nom}" /> <data:DataGridTextColumn Header="Date de dbut" Binding="{Binding Path=Dpart}" /> <data:DataGridTextColumn Header="Date buttoir" Binding="{Binding Path=Buttoir}" /> <data:DataGridTextColumn Header="Equipe" Binding="{Binding Path=Equipe}" /> </data:DataGrid.Columns> </data:DataGrid> </Grid> </UserControl>
contenant un DatePicker.
Exemple de DataGridTemplateColumn DatePicker
<data:DataGridTemplateColumn Header="Date de dbut"> <data:DataGridTemplateColumn.CellTemplate> <DataTemplate> <controls:DatePicker
263
Concepts avancs
SelectedDate="{Binding Dpart, Mode=OneWay}" /> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> <data:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <controls:DatePicker SelectedDate="{Binding Dpart, Mode=TwoWay}" /> </DataTemplate> </data:DataGridTemplateColumn.CellEditingTemplate> </data:DataGridTemplateColumn>
Deux attributs de Template sont rednir dans cet UserControl, le CellTemplate (Template utilis en mode daffichage de donnes) et le CellEditingTemplate (Template utilis en mode ddition des donnes) Le remplacement de ces DataTemplate la sauce DataGrid contribue dj beaucoup la propret de notre interface :
264
Le contrle DataGrid
<data:DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Path=Equipe}" IsReadOnly="True"> <!--<data:DataGrid.Columns> <data:DataGridTextColumn Header="Nom" Binding="{Binding Nom}"/> </data:DataGrid.Columns>--> </data:DataGrid> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> <data:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <data:DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Path=Equipe}" IsReadOnly="False"> </data:DataGrid> </DataTemplate> </data:DataGridTemplateColumn.CellEditingTemplate> </data:DataGridTemplateColumn>
Pour rendre le tout encore plus beau, nous allons crer pour chaque employ une mini carte de visite.
265
Concepts avancs
Cest maintenant que lon passe False la valeur AutoGeneretedColumn de notre DataGrid Equipe, elle-mme DataTemplate dune DataGridTemplateColumn de notre DataGrid principale :
Carte de visite pour Employs
<data:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=Equipe}" IsReadOnly="True"> <data:DataGrid.Columns> <data:DataGridTemplateColumn> <data:DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Source="{Binding Path=ImageSourcePhoto}" Height="50" Width="50" Stretch="UniformToFill"/> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Prenom}" Margin="5"/> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> </StackPanel> <HyperlinkButton Content="{Binding Blog}"/> <HyperlinkButton Content="{Binding Email}"/> </StackPanel> </StackPanel> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> </data:DataGridTemplateColumn> </data:DataGrid.Columns> </data:DataGrid> c Fig. 5.29 : DataGrid compltement customise
266
Le contrle DataGrid
Il a t ncessaire dajouter une proprit la dnition de classe Etudiant. Cette proprit est ImageSourcePhoto de type ImageSource. En effet, lattribut Source dune Image est une ImageSource et non un URI :
Proprit ImageSourcePhoto
namespace TestWindowsControls { public class Employ { (...) public ImageSource ImageSourcePhoto { get { return new BitmapImage(Photo); } } (...) } }
267
Concepts avancs
Binding="{Binding Path=Nom}" /> <data:DataGridTemplateColumn Header="Date de dbut"> <data:DataGridTemplateColumn.CellTemplate> <DataTemplate> <controls:DatePicker VerticalAlignment="Top" SelectedDate="{Binding Dpart, Mode=OneWay}" /> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> <data:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <controls:DatePicker VerticalAlignment="Top" SelectedDate="{Binding Dpart, Mode=TwoWay}" /> </DataTemplate> </data:DataGridTemplateColumn.CellEditingTemplate> </data:DataGridTemplateColumn> <data:DataGridTemplateColumn Header="Date buttoir"> <data:DataGridTemplateColumn.CellTemplate> <DataTemplate> <controls:DatePicker VerticalAlignment="Top" SelectedDate="{Binding Buttoir, Mode=OneWay}" /> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> <data:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <controls:DatePicker VerticalAlignment="Top" SelectedDate="{Binding Buttoir, Mode=TwoWay}" /> </DataTemplate> </data:DataGridTemplateColumn.CellEditingTemplate> </data:DataGridTemplateColumn> <data:DataGridTemplateColumn Header="Equipe"> <data:DataGridTemplateColumn.CellTemplate> <DataTemplate> <data:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=Equipe}" IsReadOnly="True"> <data:DataGrid.Columns> <data:DataGridTemplateColumn> <data:DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Source="{Binding Path=ImageSourcePhoto}" Height="50" Width="50"
268
Stretch="UniformToFill"/> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Prenom}" Margin="5"/> <TextBlock Text="{Binding Path=Nom}" Margin="5"/> </StackPanel> <HyperlinkButton Content="{Binding Blog}"/> <HyperlinkButton Content="{Binding Email}"/> </StackPanel> </StackPanel> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> </data:DataGridTemplateColumn> </data:DataGrid.Columns> </data:DataGrid> </DataTemplate> </data:DataGridTemplateColumn.CellTemplate> </data:DataGridTemplateColumn> </data:DataGrid.Columns> </data:DataGrid> </Grid> </UserControl>
les contrles utilisateur de saisie dinformations ; les contrles utilisateur de structuration dinformations ; les contrles utilisateur de styles et thmes.
Pour utiliser ces nouveaux contrles, il faut pralablement en tlcharger la librairie sur le site de CodePlex : http://www.codeplex.com/Silverlight/. Ensuite, pour ajouter votre projet Silverlight les diffrentes DLL en tant que rfrences :
1
269
Concepts avancs
Dans la bote de dialogue Ajouter une rfrence, slectionnez longlet Parcourir. 4 Naviguez jusqu lemplacement des DLL et slectionnez les chiers Microsoft .Windows.Controls.Theming.dl, Microsoft.Windows.Controls.DataVisualization.dll, Microsoft.Windows.Controls.dll et Microsoft.Windows.Controls.Input.dll.
3 c Fig. 5.31 : Bote de dialogue Ajouter une rfrence
Vous trouverez tous les exemples et toutes les informations ncessaires lutilisation de ces nouveaux UserControls dans le chier ZIP fourni par CodePlex.
270
Check-list
5.7 Check-list
Dans ce chapitre, nous avons amlior considrablement nos comptences en XAML, tudi des moyens efficaces pour rendre un code dinterface plus lisible ainsi que dautres moyens, tout aussi efficaces, pour obtenir leffet inverse. Le juste milieu entre un code propre et une exprience utilisateur riche ne semble pas encore accessible ; seule lexprience pourra vous aider sur cette voie. Sachez que rien nest impossible, en Silverlight, ou presque. Tout ce que vous pouvez imaginer, vous pouvez le coder ; la plateforme .Net vous y aidera.
271
6
6.1 Introduction Deepzoom .............................. 6.2 Fonctionnement de Deepzoom ........................ 6.3 Deepzoom par lexemple .............................. 6.4 Deepzoom et Virtual Earth ............................. 6.5 Check-list ................................................. 274 275 279 288 289
Dcouvrir Deepzoom
D
eepzoom est une technologie introduite dans Silverlight 2. Cest un des points forts de Silverlight. En effet, Deepzoom permet une gestion optimale des images. Nous allons dcouvrir dans ce chapitre comment utiliser cette technologie hors du commun au travers dun exemple simple mais efficace avec Deepzoom.
Dcouvrir Deepzoom
Youtube, Dailymotion et dautres se sont mis la haute rsolution. Deepzoom est l pour que vous puissiez faire de mme avec les images. Souvent, les photos sur le Web sont de mauvaise qualit ; on peut trs rarement zoomer correctement sur une image. Vous pouvez utiliser deepzoom pour afficher des images de trs grande qualit. Vous pouvez ainsi imaginer un site de visualisation dimages haute rsolution pour les photos de vacances, de mariage ou les photos professionnelles. Deepzoom permet galement une visualisation panoramique dun paysage ou dune maison. Imaginez cela pour des sites consacrs limmobilier ! Cela permet galement de nouveaux modles de publicit. En effet, le zoom peut apporter des informations supplmentaires sur un produit mis en publicit.
274
Fonctionnement de Deepzoom
Limage haute rsolution est en fait dcoupe en plusieurs images. Microsoft appelle cela la pyramide dimages. Une pyramide dimages dcompose une image en fragments de 256 x 256 dimages JPG ou PNG (dans ce cas, la taille est arbitraire et peut tre modie) et stocke galement des versions de rsolution infrieure de limage dans les fragments. Chaque fragment est stock lintrieur dun chier distinct et chaque niveau de la pyramide est stock lintrieur de dossiers distincts. Limage ci-aprs dcrit schmatiquement le fonctionnement de la pyramide dimages. Limage elle-mme est disponible en pleine rsolution dans le bas de la pyramide (voir limage ci-aprs) et les versions de rsolution infrieure jusqu 4 x 4 pixels sont stockes avec limage pleine rsolution. Les images chaque niveau de la pyramide sont stockes dans des fragments de 256 x 256 pixels (lignes blanches dans les images). DeepZoom peut ainsi extraire uniquement les fragments requis pour la taille actuelle de limage lcran, au lieu de tlcharger toute limage. Par exemple, si vous effectuez un zoom avant pour afficher uniquement la partie centrale en surbrillance de limage, DeepZoom charge uniquement les fragments en surbrillance, plutt que toute limage au format 1 024 x 1 024. La cration manuelle de ces pyramides peut se rvler fastidieuse. Par consquent, il est recommand dutiliser un outil permettant de convertir les images en une pyramide dimages. Par exemple, pour ce faire, vous pouvez utiliser DeepZoom Composer. Vous trouverez cet utilitaire sur le site de Silverlight.net.
275
Dcouvrir Deepzoom
Le format de chier qui sert accder la pyramide dimages utilise un schma XML. nouveau, vous pouvez gnrer ce format de chier laide de DeepZoom Composer. Toutefois, si vous souhaitez exercer un contrle plus prcis sur le format de chier, vous pouvez crer manuellement le code XML ou apporter des modications manuelles un chier gnr par un outil. Vous pouvez vous-mme crer un les chiers XML. Mais cela est loin dtre simple. Dabord, il gnre un chier de metadata :
<?xml version="1.0"?> <Metadata version="1"> <AspectRatio>0.733841659419689</AspectRatio> <Image> <FileName>C:\Documents and Settings\samlan\Desktop\Labs\ DeepZoomCollections\DeepZoomOutput\DeepZoomComposer\source images\tree_blossoms.jpg</FileName> <x>0</x> <y>0</y> <Width>0.429715926819635</Width> <Height>0.4739336492891</Height> <ZOrder>1</ZOrder> <Tag /> </Image> <Image> <FileName>C:\Documents and Settings\samlan\Desktop\Labs\DeepZoomCollections\ DeepZoomOutput\DeepZoomComposer\source images\guy_by_the_beach.jpg</FileName>
276
Fonctionnement de Deepzoom
<x>0.55991053434817</x> <y>0</y> <Width>0.44008946565183</Width> <Height>0.4739336492891</Height> <ZOrder>2</ZOrder> <Tag /> </Image> <Image> <FileName>C:\Documents and Settings\samlan\Desktop\Labs\ DeepZoomCollections\DeepZoomOutput\DeepZoomComposer\source images\licorice.jpg</FileName> <x>0</x> <y>0.5260663507109</y> <Width>0.431362685784476</Width> <Height>0.4739336492891</Height> <ZOrder>3</ZOrder> <Tag /> </Image> <Image> <FileName>C:\Documents and Settings\samlan\Desktop\Labs\ DeepZoomCollections\DeepZoomOutput\DeepZoomComposer\source images\flower.jpg</FileName> <x>0.579552839832946</x> <y>0.5260663507109</y> <Width>0.420447160167053</Width> <Height>0.4739336492891</Height> <ZOrder>4</ZOrder> <Tag /> </Image> </Metadata>
277
Dcouvrir Deepzoom
<FileName>C:\Documents and Settings\samlan\Desktop\Labs\ DeepZoomCollections\DeepZoomOutput\DeepZoomComposer\source images\guy_by_the_beach.jpg</FileName> <x>0.55991053434817</x> <y>0</y> <Width>0.44008946565183</Width> <Height>0.4739336492891</Height> <ZOrder>2</ZOrder> </SceneNode> <SceneNode> <FileName>C:\Documents and Settings\samlan\Desktop\Labs\ DeepZoomCollections\DeepZoomOutput\DeepZoomComposer\source images\licorice.jpg</FileName> <x>0</x> <y>0.5260663507109</y> <Width>0.431362685784476</Width> <Height>0.4739336492891</Height> <ZOrder>3</ZOrder> </SceneNode> <SceneNode> <FileName>C:\Documents and Settings\samlan\Desktop\Labs\ DeepZoomCollections\DeepZoomOutput\DeepZoomComposer\source images\flower.jpg</FileName> <x>0.579552839832946</x> <y>0.5260663507109</y> <Width>0.420447160167053</Width> <Height>0.4739336492891</Height> <ZOrder>4</ZOrder> </SceneNode> </SceneGraph>
Il gnre enn un chier contenant des informations sur les images et des rfrences vers les metadata de chacune des images :
<?xml version="1.0" encoding="UTF-8"?> <Collection MaxLevel="8" TileSize="256" Format="png" NextItemId="4" xmlns="http://schemas.microsoft.com/deepzoom/2008"> <Items> <I Id="0" N="0" IsPath="1" Source="dzc_output_images/tree_blossoms.xml"> <Size Width="515" Height="774" /> <Viewport Width="2.32711864" X="0" Y="0" /> </I> <I Id="1" N="1" IsPath="1" Source="dzc_output_images/guy_by_the_beach.xml"> <Size Width="569" Height="835" /> <Viewport Width="2.2722652" X="-1.2722652" Y="0" /> </I>
278
<I Id="2" N="2" IsPath="1" Source="dzc_output_images/licorice.xml"> <Size Width="531" Height="795" /> <Viewport Width="2.318235" X="0" Y="-1.66186452" /> </I> <I Id="3" N="3" IsPath="1" Source="dzc_output_images/flower.xml"> <Size Width="541" Height="831" /> <Viewport Width="2.37842" X="-1.37842011" Y="-1.70500922" /> </I> </Items> </Collection>
Vous voyez galement une srie de dossiers : 1, 2, 3, 4, etc. Ces dossiers contiennent une ou plusieurs images. Elles reprsentent llment de plus en plus grand.
La zone pour les images est un peu particulire ; cest une zone spcique Deepzoom que vous navez probablement jamais rencontre auparavant. Cest un objet XAML MultiScaleImage :
<MultiScaleImage Height="600" x:Name="msi" Source="GeneratedImages/dzc_output.xml" Width="800"/>
279
Dcouvrir Deepzoom
Cette zone fait rfrence au chier XML que nous avons vu prcdemment et qui ressemble ceci :
<?xml version="1.0" encoding="UTF-8"?> <Collection MaxLevel="8" TileSize="256" Format="png" NextItemId="4" xmlns="http://schemas.microsoft.com/deepzoom/2008"> <Items> <I Id="0" N="0" IsPath="1" Source="dzc_output_images/tree_blossoms.xml"> <Size Width="515" Height="774" /> <Viewport Width="2.32711864" X="0" Y="0" /> </I>
Une fois que vous avez assimil le nouvel lment XAML, le code nest pas trs compliqu :
<UserControl x:Class="DeepZoomProject.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
280
Width="800" Height="600"> <Grid x:Name="LayoutRoot" Background="White"> <Border BorderBrush="#FF727272" BorderThickness="1,1,1,1"> <MultiScaleImage Height="600" x:Name="msi" Source="GeneratedImages/dzc_output.xml" Width="800"/> </Border> <Button Height="31" Width="286" Content="Randomize Images" Click="Arrange_Click"/> </Grid> </UserControl>
Sur notre MultiScaleImage, nous allons dclarer une srie dvnements qui nous permettront de savoir ce que fait lutilisateur sur lapplication (clic, dplacement, etc.). Ceci se fera dans le constructeur de notre page (dans le code behind, code attach) :
msi.MouseMove += delegate(object sender, MouseEventArgs e) { if (mouseButtonPressed) { mouseIsDragging = true; } this.lastMousePos = e.GetPosition(this.msi); }; msi.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e) { mouseButtonPressed = true; mouseIsDragging = false; dragOffset = e.GetPosition(this); currentPosition = msi.ViewportOrigin; }; msi.MouseLeave += delegate(object sender, MouseEventArgs e) { mouseIsDragging = false; }; msi.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e) { mouseButtonPressed = false; if (mouseIsDragging == false) { bool shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; ZoomFactor = 2.0; if (shiftDown) ZoomFactor = 0.5;
281
Dcouvrir Deepzoom
Zoom(ZoomFactor, this.lastMousePos); } mouseIsDragging = false; }; msi.MouseMove += delegate(object sender, MouseEventArgs e) { if (mouseIsDragging) { Point newOrigin = new Point(); newOrigin.X = currentPosition.X - (((e.GetPosition(msi).X dragOffset.X) / msi.ActualWidth) * msi.ViewportWidth); newOrigin.Y = currentPosition.Y - (((e.GetPosition(msi).Y dragOffset.Y) / msi.ActualHeight) * msi.ViewportWidth); msi.ViewportOrigin = newOrigin; } };
On voit apparatre lutilisation dune fonction Zoom, fonction que lon utilise pour atteindre un point :
public void Zoom(double zoom, Point pointToZoom) { Point logicalPoint = this.msi.ElementToLogicalPoint(pointToZoom); this.msi.ZoomAboutLogicalPoint(zoom, logicalPoint.X, logicalPoint.Y); }
Tout ce code ne prend malheureusement pas en compte la molette de la souris qui est pourtant trs utilise. Pour cela, nous pouvons crer une classe qui prendra en compte cette molette. Cette classe a t dnie au dpart par Pete Bois et adapte au projet. Vous trouverez le code de cette classe la n du chapitre. Vous pouvez vous attacher aux vnements de la molette de la manire suivante :
new MouseWheelHelper(msi).Moved += delegate(object sender, MouseWheelEventArgs e) { e.Handled = true; if (e.Delta > 0) ZoomFactor = 1.2; else ZoomFactor = .80; Zoom(ZoomFactor, this.lastMousePos); };
282
Dans notre programme, il faut juste grer correctement le clic sur le bouton au milieu de notre application Silverlight. Pour cela, une fonction intercepte lvnement click de notre bouton :
private void Arrange_Click(object sender, RoutedEventArgs e) { ArrangeIntoGrid(); }
Cette fonction va rarranger les images. Nous devons crer une animation. Vous avez vu dans un chapitre prcdent ce qutait les storyboards. Nous allons ici crer un storyboard de faon dynamique, cest--dire directement dans le code :
Storyboard moveStoryboard = new Storyboard();
Ensuite, il faut crer lanimation et les frames qui vont intervenir dedans :
// Create Animation PointAnimationUsingKeyFrames moveAnimation = new PointAnimationUsingKeyFrames(); // Create Keyframe SplinePointKeyFrame startKeyframe = new SplinePointKeyFrame(); startKeyframe.Value = currentPosition; startKeyframe.KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero); startKeyframe = new SplinePointKeyFrame(); startKeyframe.Value = futurePosition; startKeyframe.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)); KeySpline ks = new KeySpline(); ks.ControlPoint1 = new Point(0, 1); ks.ControlPoint2 = new Point(1, 1); startKeyframe.KeySpline = ks; moveAnimation.KeyFrames.Add(startKeyframe); Storyboard.SetTarget(moveAnimation, currentImage); Storyboard.SetTargetProperty(moveAnimation, new PropertyPath("ViewportOrigin")); moveStoryboard.Children.Add(moveAnimation); msi.Resources.Add("unique_id", moveStoryboard); // Play Storyboard moveStoryboard.Begin();
283
Dcouvrir Deepzoom
La seule chose faire auparavant est de rorganiser les images. Pour cela, nous disposons dune liste dimages qui est renvoye par notre fonction. Cette liste dtermine lordre :
private List<MultiScaleSubImage> RandomizedListOfImages() { List<MultiScaleSubImage> imageList = new List<MultiScaleSubImage>(); Random ranNum = new Random(); // Store List of Images foreach (MultiScaleSubImage subImage in msi.SubImages) { imageList.Add(subImage); } int numImages = imageList.Count; // Randomize Image List for (int i = 0; i < numImages; i++) { MultiScaleSubImage tempImage = imageList[i]; imageList.RemoveAt(i); int ranNumSelect = ranNum.Next(imageList.Count); imageList.Insert(ranNumSelect, tempImage); } return imageList; }
Ensuite, on effectue une boucle sur le nombre de colonnes de notre application (3) et sur le nombre dimages par colonne (nombre dimages/nombre de colonnes 1 ) . Ce sont les seules choses dont vous avez besoin pour crer cette application utilisant Deepzoom. Vous pourrez retrouver lexemple complet dans le code livr avec le livre sur le site de Micro Application.
284
MouseWheelHelper.cs
using using using using using using using using using using using System; System.Net; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Windows.Browser;
namespace DeepZoomProject { // Courtesy of Pete Blois public class MouseWheelEventArgs : EventArgs { private double delta; private bool handled = false; public MouseWheelEventArgs(double delta) { this.delta = delta; } public double Delta { get { return this.delta; } } // Use handled to prevent the default browser behavior! public bool Handled { get { return this.handled; } set { this.handled = value; } } } public class MouseWheelHelper { public event EventHandler<MouseWheelEventArgs> Moved; private static Worker worker; private bool isMouseOver = false;
285
Dcouvrir Deepzoom
public MouseWheelHelper(FrameworkElement element) { if (MouseWheelHelper.worker == null) MouseWheelHelper.worker = new Worker(); MouseWheelHelper.worker.Moved += this.HandleMouseWheel; element.MouseEnter += this.HandleMouseEnter; element.MouseLeave += this.HandleMouseLeave; element.MouseMove += this.HandleMouseMove; } private void HandleMouseWheel(object sender, MouseWheelEventArgs args) { if (this.isMouseOver) this.Moved(this, args); } private void HandleMouseEnter(object sender, EventArgs e) { this.isMouseOver = true; } private void HandleMouseLeave(object sender, EventArgs e) { this.isMouseOver = false; } private void HandleMouseMove(object sender, EventArgs e) { this.isMouseOver = true; } private class Worker { public event EventHandler<MouseWheelEventArgs> Moved; public Worker() { if (HtmlPage.IsEnabled) { HtmlPage.Window.AttachEvent("DOMMouseScroll", this.HandleMouseWheel);
286
HtmlPage.Window.AttachEvent("onmousewheel", this.HandleMouseWheel); HtmlPage.Document.AttachEvent("onmousewheel", this.HandleMouseWheel); } } private void HandleMouseWheel(object sender, HtmlEventArgs args) { double delta = 0; ScriptObject eventObj = args.EventObject; if (eventObj.GetProperty("wheelDelta") != null) { delta = ((double)eventObj.GetProperty("wheelDelta")) / 120;
if (HtmlPage.Window.GetProperty("opera") != null) delta = -delta; } else if (eventObj.GetProperty("detail") != null) { delta = -((double)eventObj.GetProperty("detail")) / 3; if (HtmlPage.BrowserInformation.UserAgent.IndexOf ("Macintosh") != -1) delta = delta * 3; } if (delta != 0 && this.Moved != null) { MouseWheelEventArgs wheelArgs = new MouseWheelEventArgs(delta); this.Moved(this, wheelArgs); if (wheelArgs.Handled) args.PreventDefault(); } } }
287
Dcouvrir Deepzoom
} }
La partie la plus importante est la partie o nous allons attacher les vnements :
public Worker() { if (HtmlPage.IsEnabled) { HtmlPage.Window.AttachEvent("DOMMouseScroll", this.HandleMouseWheel); HtmlPage.Window.AttachEvent("onmousewheel", this.HandleMouseWheel); HtmlPage.Document.AttachEvent("onmousewheel", this.HandleMouseWheel); } }
288
Check-list
6.5 Check-list
Dans ce chapitre sur Deepzoom, nous avons tudi :
a llment XAML MultiScaleImage ; a la manipulation des images dans Deepzoom laide de Deepzoom Composer.
289
7
7.1 Silverlight et les langages dynamiques ............... 7.2 Introduction au C# ...................................... 7.3 Webographie ........................................... 292 299 311
Annexes
Annexes
Silverlight et IronPyhton
Il faut savoir que la DLR, outil indispensable pour utiliser les langages dynamiques, est encore en dveloppement. Tous les tests que vous pouvez actuellement effectuer se font sur un composant en dveloppement. La DLR et les langages dynamiques ont t cons la communaut (en grande partie). Cest donc une dmarche de Microsoft vers lOpenSource. Cela amne de nombreux avantages mais aussi certains inconvnients. Ces langages ne sont pas encore bien intgrs Visual Studio. Comme vous allez le voir, nous devrons repasser en ligne de commandes pour crer notre projet IronPython. Cela devrait tre rgl peu de temps aprs la parution de ce livre dans le courant de 2009. En attendant, vous devez vous procurer le SDK de dveloppement. Ce SDK peut tre trouv sur le site de Silverlight.NET. Une fois install, vous pouvez ouvrir votre utilitaire de commande et vous rendre dans le dossier script du chier tlcharg. Pour crer un projet, il faut ensuite utiliser cette ligne de commandes :
> script/sl [ruby|python|jscript] <application_name>
Par exemple :
> script/sl python testPythonApp
De cette manire, un projet est gnr dans un dossier testPyhtonApp. lintrieur, vous trouvez quelques chiers dont un index et deux dossiers. Dans les deux dossiers, vous avez un chier de style ainsi que deux chiers composant lapplication Silverlight : un chier XAML et un chier Python. Vous pouvez les ouvrir avec Visual Studio :
<UserControl x:Class="System.Windows.Controls.UserControl" xmlns="http://schemas.microsoft.com/client/2007"
292
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="layout_root" Background="White"> <TextBlock x:Name="Message" FontSize="30" /> </Grid> </UserControl>
Pour gnrer ensuite un chier xap, vous avez besoin dun petit utilitaire appel Chiron. Vous pouvez trouver cet utilitaire dans le package que vous avez tlcharg (SDK de la DLR). Cet utilitaire sutilise de la manire suivante :
Chiron.exe /directory:MyApp\app /zipdlr:app.xap
Nous vous conseillons de dplacer le contenu du chier bin dans le rpertoire o vous voulez crer votre chier xap. Aprs avoir obtenu ce chier, vous avez toutes les cartes en main pour crer correctement une application Silverlight avec des langages dynamiques.
293
Annexes
<Storyboard> <DoubleAnimation x:Name="hourAnimation" Storyboard.TargetName="hourHandTransform" Storyboard.TargetProperty="Angle" From="180" To="540" Duration="12:0:0" RepeatBehavior="Forever"/> <DoubleAnimation x:Name="minuteAnimation" Storyboard.TargetName="minuteHandTransform" Storyboard.TargetProperty="Angle" From="180" To="540" Duration="1:0:0" RepeatBehavior="Forever"/> <DoubleAnimation x:Name="secondAnimation" Storyboard.TargetName="secondHandTransform" Storyboard.TargetProperty="Angle" From="180" To="540" Duration="0:1:0" RepeatBehavior="Forever"/> <DoubleAnimation Storyboard.TargetName="parentCanvas" Storyboard.TargetProperty="Opacity" From="0" To="0.7" Duration="0:0:4"/> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Canvas.Triggers>
Une horloge est galement caractrise par une aiguille pour les heures, les minutes et les secondes. Les animations pour ces lments sont cres dans le storyboard :
<!-- Hour hand --> <Path Data="M -4, 16 l 3 40 3 0 2 -40 z" Fill="white"> <Path.RenderTransform> <TransformGroup> <RotateTransform x:Name="hourHandTransform" Angle="180"/> <TranslateTransform X="150.5" Y="145"/> </TransformGroup> </Path.RenderTransform> </Path> <!-- Minute hand --> <Path Data="M -4, 16 l 3 70 3 0 2 -70 z" Fill="white"> <Path.RenderTransform> <TransformGroup> <RotateTransform x:Name="minuteHandTransform"
294
Angle="180"/> <TranslateTransform X="150.5" Y="145"/> </TransformGroup> </Path.RenderTransform> </Path> <!-- Second hand --> <Path Data="M -1, 16 l 0 70 2 0 0 -70 z" Fill="red"> <Path.RenderTransform> <TransformGroup> <RotateTransform x:Name="secondHandTransform" Angle="180"/> <TranslateTransform X="150.5" Y="145"/> </TransformGroup> </Path.RenderTransform> </Path>
Ensuite, il faut donner un dcor notre horloge (la face, une petite ombre, etc.) :
<!-- Drop shadow --> <Path Data="M 157, 5 a 150,150 0 1,0 1,0 z"> <Path.Fill> <SolidColorBrush Color="Black" Opacity="0.3"/> </Path.Fill> </Path> <!-- Clock bezel --> <Path Data="M 150, 0 a 150,150 0 1,0 1,0 z" Fill="black" /> <Path Data="M 150, 1 a 149,149 0 1,0 1,0 z" > <Path.Fill> <LinearGradientBrush> <LinearGradientBrush.GradientStops> <GradientStopCollection> <GradientStop Color="silver" Offset="0.05"/> <GradientStop Color="#333333" Offset="0.95"/> </GradientStopCollection> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Path.Fill> </Path> <Path Data="M 150, 15 a 135,135 0 1,0 1,0 z" Fill="black" Opacity="1"/> <Path Data="M 150, 16 a 134,134 0 1,0 1,0 z" Opacity="1"> <Path.Fill> <LinearGradientBrush> <LinearGradientBrush.GradientStops>
295
Annexes
<GradientStopCollection> <GradientStop Color="#333333" Offset="0.05"/> <GradientStop Color="silver" Offset="0.95"/> </GradientStopCollection> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Path.Fill> </Path> <!-- Clock face --> <Path Data="M 150, 23 a 127,127 0 1,0 1,0 z" Fill="black" Opacity="1"/>
Il ne reste plus qu ajouter un peu de code Python, qui ira chercher la date actuelle et placer les aiguilles en consquence :
from System.Windows import Application from System.Windows.Controls import Canvas from datetime import datetime class Clock: def __init__(self): self.scene = Application.Current.LoadRootVisual(Canvas(), "app.xaml") def fromAngle(self, time, divisor = 5, offset = 0): return ((time / (12.0 * divisor)) * 360) + offset + 180 def toAngle(self, time): return self.fromAngle(time) + 360 def start(self): d = datetime.now() self.scene.hourAnimation.From = self.fromAngle(d.hour, 1, d.minute/2) self.scene.hourAnimation.To = self.toAngle(d.hour) self.scene.minuteAnimation.From = self.fromAngle(d.minute) self.scene.minuteAnimation.To = self.toAngle(d.minute) self.scene.secondAnimation.From = self.fromAngle(d.second) self.scene.secondAnimation.To = self.toAngle(d.second) Clock().start()
296
Silverlight et IronRuby
Ruby fait galement partie des langages que supporte la DLR. Il est trs apprci de la communaut des dveloppeurs pour sa facilit et les nombreux paradigmes quil permet de dvelopper (fonctionnel, objet, etc.). Pour la cration dune application Ruby et Silverlight, cest le mme principe que pour Pyhton (IronPython) :
> script/sl ruby testRubyApp
Seule diffrence, il y a trois chiers au niveau du dossier app. Le fonctionnement est pourtant le mme. Le troisime chier ajout (Silverlight.rb) est une classe (SilverlightApplication) qui permet dtablir la liaison avec le chier XAML :
include System::Windows include System::Windows::Controls include System::Windows::Media class SilverlightApplication def application Application.current end def self.use_xaml(options = {}) options = {:type => UserControl, :name => "app"}.merge(options) Application.current.load_root_visual(options[:type].new, "#{options[:name]}.xaml") end def root application.root_visual end def method_missing(m) root.send(m) end end class FrameworkElement def method_missing(m) find_name(m.to_s.to_clr_string) end end
297
Annexes
Cette classe sera toujours la mme et vous ne devrez probablement jamais rien changer lintrieur. Le plus important se trouve dans le chier app.rb.
298
Introduction au C#
Check-list
Nous avons tudi dans cette annexe :
j j j
7.2 Introduction au C#
Le C# est un langage de programmation typage fort et orient objet. Cela sous-entend :
j
Typage fort. Chaque variable doit tre dnie et respecte le type de sa dnition. Une variable dclare comme nombre entier restera un nombre entier tout au long de sa porte et ne pourra utiliser que les mthodes soit appartenant au type nombre entier soit utilisant le type nombre entier. Orient objet. Il est possible de dnir de nouveaux types nomms classes. Une classe est une structure de donnes pouvant contenir des fonctions.
Il existe donc deux sortes de types en C#, les types primitifs (nombre entier, nombre rel, chane de caractres, etc.) et les types de classe. Une variable instancie comme tant de type classe porte le nom dobjet.
299
Annexes
Un type primitif commence toujours par une minuscule. Si vous rencontrez un type commenant par une majuscule, cest quil sagit dun type de classe.
Rgles de nommage
Le nom des variables :
j j j
Commence par une lettre ou un caractre de soulignement. Indique clairement son contenu. Peut contenir invariablement des minuscules, majuscules, des chiffres et des caractres de soulignement. Attention, le C# considre comme diffrentes deux variables du mme nom dont seule la case change. (VaRiable1 et Variable1 ne sont pas les mmes variables.)
La convention de choix du nom de variable la plus courante est le CamelCase du nom anglais des chameaux. Tels les bosses dun chameau, chaque nouveau mot dans le nom dune variable commence par une majuscule. Cette convention simplie grandement la lecture. Comparez votre guise ces deux versions du mme nom :
j j
lavariablequivameservirdanslaboucledemonapplicationpourcalculerlatvasurmonsalaire ; LaVariableQuiVaMeServirDansLaBoucleDeMonApplicationPourCalculerLaTvaSurMonSalaire.
Il est vident quun nom de variable si long est aberrant et ne se retrouvera jamais dans un programme.
300
Introduction au C#
Attention, dans le cas de la variable de nom ChaineVide, seule la dclaration du nom de la variable t assigne, mais aucune zone mmoire na t alloue via le mot-cl new. On dit de la variable ChaineVide quelle est null.
Ce qui est vrai pour les types de classe ne lest pas pour les types primitifs. Un type primitif reprsente directement sa zone mmoire. Le mme exemple en type primitif reviendrait copier le contenu de la zone mmoire de nombre2 dans la zone mmoire de nombre1. Revenons nos types de classe. Quest-il advenu de la zone mmoire dnie en ligne 1 ?
301
Annexes
La rponse est simple : elle nexiste plus. Lorsquune zone mmoire nest plus pointe par aucun nom de variable, cette zone mmoire est recycle par le ramasseur de poubelle de la plateforme .NET.
La variable nombre1 est accessible de la ligne 2 la ligne 10. La variable chane dnie en ligne 3 est accessible : - la ligne 3 ; - de la ligne 7 la ligne 10.
En effet, la variable chane dclare en ligne 5, dans un autre bloc de code, prvaut dans son bloc sur la variable chane dclare en ligne 3. Cependant, en ligne 5, il est possible dutiliser la variable nombre1 dnie en ligne 2, car aucune autre variable du nom nombre1 na t dnie dans le blog de la ligne 4 la ligne 7. De la mme faon, les variables nombre2 en ligne 6 et nombre2 en ligne 9 sont deux variables diffrentes. Chaque variable est recycle par le ramasseur de poubelle la n de son bloc ; la variable nombre2 de la ligne 6 cesse donc dexister en ligne 7.
302
Introduction au C#
Dans cet exemple, la mthode ToString de la variable nombre est appele. Cette mthode convertit la variable en une chane de caractres qui sera ensuite assigne la variable s.
303
Annexes
Exemple de using
using Sytem; using Sytem.Net;
Ce qui suit est un namespace. Un namespace ou espace de noms est une sorte denclos dnissant une famille. Si dans la famille Boigelot, le nom de Simon signie un des auteurs de ce Livre, dans la famille Bible, Simon dnit un aptre. Il en va de mme pour les espaces de noms. Ensuite vient une dnition de classe car en C#, tout est objet.
304
Introduction au C#
Le mot-cl public devant chaque proprit signie quon peut accder cette proprit par lextrieur de la classe. Ainsi il est possible dcrire :
Dclaration dun objet de classe Personne
Personne p = new Personne(); p.Nom = " Simon pas moi mais laptre "; p.age = 2000;
Son nom doit respecter les mmes rgles que ceux des variables. Son type de retour est le type de rsultat de la mthode, par exemple pour la mthode Add additionnant deux nombres entiers, le type de retour sera un nombre entier. Ses paramtres, pour la mme mthode Add, les paramtres de la mthode seront les deux nombres entiers additionner.
Le mot-cl return est suivi du rsultat de la mthode. En effet, une mthode peut tre longue et demander de nombreuse lignes de code. Ce mot-cl stipule la plateforme le rsultat retourner. Utiliser cette mthode savre aussi simple mais les types de variables des paramtres doivent tre respects sous peine dobtenir une erreur.
Utilisation de la mthode Add
int ArgentEnPoche = 5 ; int ArgentEnChausette = 1 ; int ArgentTotal = Add(ArgentEnPoche,ArgentEnChausette) ;
305
Annexes
Cette mthode est elle aussi prcde du mot-cl public pour y accder depuis lextrieur de la classe. Il est maintenant possible dcrire :
Utilisation dune mthode de classe.
Personne p = new Personne(); int somme = p.Add(342,453);
306
Introduction au C#
using System.Linq; using System.Text; namespace AnnexeConsoleApplication { class Program { static void Main(string[] args) { } } }
La classe Program contient une mthode de base, cette mthode est la mthode Main, cest elle qui sera appele par la plateforme au dmarrage du programme. Elle est prcde du mot-cl static. Ce dernier stipule que cette mthode nest dnie quune fois travers toutes les variables. Il est possible daccder aux mthodes et proprits static sans initialiser de variable. Cela se fait en crivant le nom de la classe suivi dun point et du nom de la proprit ou de la mthode. Ainsi, le code de la plateforme excutant tout programme console est :
code de la plateforme excutant tout programme console
Program.Main(paramtes) ;
307
Annexes
Nous devons ensuite dnir les donnes que nous allons grer. Un bon exemple serait de grer une bibliothque. Les diffrentes classes que nous retrouvons dans une application de gestion de bibliothques sont :
j j j
Un client emprunte un livre pour une certaine dure et paie un certain prix. Un client rapporte un livre.
namespace GestionDeDonnees { public class Livre { public string Titre; public string Auteur; public DateTime Echeance; public int NombreDePage; public int Prix; } }
308
Introduction au C#
namespace GestionDeDonnees { public class Bibliotheque { public List<Livre> LivreEnMagasin = new List<Livre>(); public List<Client> Clientelle = new List<Client>(); } }
Dans ce cas, la liste attire sans doute votre regard. En C#, il est possible de dclarer une proprit comme tant une liste dobjets. Cette liste na pas de taille. Pour y ajouter un objet, il suffit den appeler la mthode Add(Objet o). Ainsi pour ajouter un Livre la liste LivreEnMagasin, vous utiliserez le code :
Liste.Add
Livre MonLivre = new Livre() ; Bibliothque.LivreEnMagasin.Add(MonLivre) ;
Pour atteindre un livre dans une liste, on peut utiliser son index, sa position dans la liste :
Utilisation des index dans une liste
Livre MonLivre = Bibliothque.LivreEnMagasin[4]
309
Annexes
namespace GestionDeDonnees { public class Client { public string Nom; public List<Livre> LivesEnEmprunt = new List<Livre>(); } }
namespace GestionDeDonnees { class Program { private Bibliotheque bibli = new Bibliotheque(); static void Main(string[] args) { }
310
Webographie
public void Emprunte(Client client, Livre livre) { bibli.LivreEnMagasin.Remove(livre); client.LivesEnEmprunt.Add(livre); } public void Rend(Client client, Livre livre) { client.LivesEnEmprunt.Remove(livre); bibli.LivreEnMagasin.Add(livre); } } }
Conclusion
Le C# est un langage trs structurant. Dans les nombreuses librairies offertes par la plateforme .NET se trouvent par milliers des dnitions de classe, les proprits et leurs mthodes. Ces mthodes, empiles couches sur couches, ont ajout une couche dabstraction par rapport au langage machine et aux autres langages de premire et deuxime gnration. Des mthodes telles que Mail.Send(Email mail) ou monPlayerVideo.PlayVideo (maVideo) forment la nourriture journalire du dveloppeur C#.
Check-list
Dans cette annexe, nous avons appris les rudiments de la programmation C#, et travers elle, les rudiments de la programmation oriente objet. Nous esprons que cette annexe aidera celles et ceux dentre vous qui dbutent plein de courage dans ce monde merveilleux de la programmation. Mais noubliez jamais quInternet est votre ami. De nombreux tutoriaux sont disponibles sur le sujet pour toutes personnes dsireuses den apprendre plus.
7.3 Webographie
Ce livre naura pas fait de vous un expert. Vous possdez toutes les bases ncessaires pour crer de trs bonnes applications Silverlight. Mais malheureusement, de Silverlight dcoule un grand nombre dautres technologies que nous navons pas pu aborder en dtail
311
Annexes
dans cet ouvrage. Cest pour cela que nous allons vous fournir une srie de liens sur diffrents sujets an que vous puissiez approfondir vos connaissances.
Sources officielles
Le site de Microsoft qui permet dobtenir toute linformation sur Visual Studio :
j
http://www.microsoft.com/france/msdn/vstudio/default.mspx
Une srie de vidos que vous pouvez regarder. Quelques-unes prsentent Visual Studio 2010 qui sera le prochain Visual Studio :
j
http://msdn.microsoft.com/fr-fr/vstudio/msdn.5minutes.pour.comprendre.visualstudio.aspx
http://www.microsoft.com/Express/
Le portail des dveloppeurs ddi Visual Studio. Dcouvrez-y tout ce que voulez savoir sur Visual Studio 2008 :
j
http://msdn.microsoft.com/en-us/vstudio/default.aspx
Silverlight
Silverlight est le sujet de ce livre. Nous avons abord de nombreux thmes mais peut-tre reste-t-il des pistes explorer. Dans tous les cas, il est intressant de se tenir inform pour un ventuel Silverlight 3 ou la sortie de Silverlight pour application mobile
Sources officielles
Le site officiel de Silverlight. Vous y trouverez des actualits, des dmonstrations, etc. visiter quotidiennement :
j
http://silverlight.net/
312
Webographie
http://msdn.microsoft.com/fr-fr/silverlight/default.aspx
Communauts
Pour vous tenir informer des dernires nouveauts de Silverlight en franais :
j
http://www.silverlight-info.fr/
http://blogs.codes-sources.com/guillaume/default.aspx
Le blog de Christophe Lauer est un bon blog pour se tenir inform sur lactualit autour de Microsoft, dont celle de Silverlight :
j
http://blogs.msdn.com/clauer/default.aspx
Le blog de Scott Guthrie est un incontournable pour ceux qui voudraient tre au courant de tout la premire minute. Des exemples complets sur les dernires technologies :
j
http://weblogs.asp.net/scottgu/archive/2007/05/07/silverlight.aspx
http://silverlight.net/blogs/jesseliberty/
On ne saurait les lister tous tellement il y a dinformation. Utilisez Google pour davantage de liens.
Le Framework .NET
Voici la dernire et plus grande partie explorer. Le Framework .NET est un ensemble de technologies qui permettent aussi bien de crer des applications Silverlight, que web ou encore mobile en passant par des applications Desktop. Un trs grand nombre de produits gravitent autour de cette technologie qui ne cesse de samliorer danne en anne.
Sources officielles
Source officielle de Framework .NET de Microsoft :
j
http://www.microsoft.com/NET/
313
Annexes
http://www.msdn.com
Communauts
Trs importante communaut autour du .NET. Vous y dcouvrirez un forum, de lactualit et un grand nombre darticles :
j
http://dotnet.developpez.com/
Codes-Sources est la communaut par dfaut o tous les dveloppeurs .NET se rencontrent. Ce site rpertorie les derniers postes de blog de la communaut :
j
http://blogs.codes-sources.com/
Comme son nom lindique, vous trouverez normment de code tlcharger sur ce site :
j
http://www.codes-sources.com
http://blogs.codes-sources.com/loicbar/
http://www.simonboigelot.com/
Voil qui nous a permis de faire le tour des sites avec lesquels il faut entretenir un contact. Bien entendu, au fur et mesure de vos visites, vous en dcouvrirez dautres.
314
INDEX
A
ActualHeight ............................................................................................... 243 ActualWith .................................................................................................. 243 ADO.NET ................................................................................................... 143 Adobe ........................................................................................................... 98 Animations .................................................................................................... 88 Apache ........................................................................................................ 184 ASMX ........................................................................................................ 135 Asp TreeView ................................................................................................... 195 ASP.NET ............................................................................................... 97, 182 MemberShip Provider ............................................................................... 197 Assembly .................................................................................................... 225 Auto .............................................................................................................. 33 AutoGeneratedColumn ................................................................ 253, 256, 264 AutoReverse .................................................................................................. 82
B
Background ................................................................................................... 74 BeginInvoke ................................................................................................ 242 BeginTime .................................................................................................... 82 Binding ......................................................................................................... 55 Border ........................................................................................................... 33 BorderColor .................................................................................................. 74 Brush ............................................................................................................ 73 Brushes ......................................................................................................... 73
C
Calendar .............................................................................................. 247, 249 CallBack ..................................................................................................... 146 Canvas .......................................................................................................... 31
316
INDEX
CellEditingTemplate .................................................................................... 264 Center ........................................................................................................... 77 CheckBox ................................................................................................ 42-43 Checked ................................................................................................ 43 45 Clic ......................................................................................................... 39, 54 CodePlex ..................................................................................................... 269 Collapsed .................................................................................................... 244 ColumnDenition .......................................................................................... 28 ComboBox .................................................................................................... 49 ComboBoxItem ............................................................................................. 49 CompareValidator ........................................................................................ 193 Content ................................................................................................... 40, 45 ContentPresenter ......................................................................................... 224 ControlTemplate ................................................................................... 222-223 Convert ......................................................................................................... 67 ConvertBack ................................................................................................. 67 CornerRadius ................................................................................................ 35 CustomValidator .......................................................................................... 193
D
Data ............................................................................................................ 230 DataBinding .................................................................................. 55, 214, 217 DataContext .......................................................................... 148, 216-217, 235 DataGrid ..................................................................................... 253, 255, 264 DataGridCheckBoxColumn .................................................................. 255, 257 DataGridTemplateColumn ................................................................... 255, 257 DataGridTextColumn ................................................................................... 255 DataReader .................................................................................................. 119 DataTemplate .............................................................................................. 255 DataTemplates ............................................................................................... 61 DatePicker ........................................................................................... 249, 263 DateTime .................................................................................................... 249 Decade ........................................................................................................ 248 Deepzoom ............................................................................................ 273-274
317
INDEX
Default.aspx ................................................................................................ 184 Default.aspx.cs ............................................................................................ 184 Dgrad ........................................................................................................ 76 DELETE ..................................................................................................... 116 DependencyProperties ................................................................................. 228 Disabled ........................................................................................................ 33 Dispatcher ................................................................................................... 242 DisplayDate .......................................................................................... 248-249 DisplayDateEnd .................................................................................... 248-249 DisplayDateStart ................................................................................... 248-249 DisplayMode ............................................................................................... 248 Document ...................................................................................................... 24 DOM ........................................................................................................... 210 DoubleAnimationUsingKeyFrame ................................................................. 82 Duration ........................................................................................................ 82 DynamicResource ......................................................................................... 65
E
lment ......................................................................................................... 24 EndPoint ....................................................................................................... 76 vnements ................................................................................................... 38 Expression Blend .......................................................................................................... 97 Design ........................................................................................................ 99 Encoder 2 ................................................................................................ 102 Media 2 ..................................................................................................... 98 Studio ......................................................................................................... 98 Web ............................................................................................................ 97
F
Flash/Flex ................................................................................................... 107 Foreground .................................................................................................... 74
318
INDEX
Forever ......................................................................................................... 82 Form ........................................................................................................... 185 FROM ......................................................................................................... 116 FullScreen ................................................................................................... 243 FullScreenChanged ...................................................................................... 243
G
Generic.XAML ............................................................................................. 72 GradientOrigin .............................................................................................. 77 Gradients ....................................................................................................... 73 Grid .............................................................................................................. 26 GridSplitter ................................................................................................. 251 GridView ............................................................................................. 188, 193 GroupName ................................................................................................... 45
H
Hackers ....................................................................................................... 117 Hidden .......................................................................................................... 33 HorizontalScrollBarVisibility ......................................................................... 33 HTML ......................................................................................................... 210
I
Illustrator ...................................................................................................... 98 ImageBrush ................................................................................................... 78 Images .......................................................................................................... 35 INSERT ....................................................................................................... 116 IronPyhton .................................................................................................. 292 IronRuby .............................................................................................. 297-298 IsChecked .......................................................................................... 42-43, 45 IsCheked ....................................................................................................... 45 IsFullScreen ................................................................................................ 242
319
INDEX
IsOpen .......................................................................................................... 54 IsSelectedChanged ....................................................................................... 252 IsThreeState ....................................................................................... 42, 44-45 ItemPanel ...................................................................................................... 72 ItemSource .................................................................................................... 62 ItemsSource ................................................................................................. 262 ItemTemplate ................................................................................................ 61 IValueConverter ............................................................................................ 67
K
Key ............................................................................................................... 64 KeyDown ...................................................................................................... 40 KeyUp .......................................................................................................... 40
L
Label ........................................................................................................... 188 LargeChange ................................................................................................. 51 Layout ........................................................................................................... 26 Line .............................................................................................................. 51 LinearGradientBrush ..................................................................................... 74 LINQ ................................................................................................... 113, 126 to Entities ................................................................................................. 134 to Object .................................................................................................. 126 to XML ..................................................................................................... 129 ListBox ................................................................................................... 47, 72 ListBoxItem .................................................................................................. 47 Live Encoding ............................................................................................. 103 Login .......................................................................................................... 196 LostFocus .................................................................................................... 218
320
INDEX
M
Margin .......................................................................................................... 35 Maximum ............................................................................................... 37, 51 MediaElement ............................................................................................. 237 MediaPlayer ................................................................................................ 201 MemberShip Provider ................................................................................. 197 Microsoft.Windows.Controls.Data ................................................................ 255 Minimum ................................................................................................ 37, 51 Mode ........................................................................................................... 218 Mounth ....................................................................................................... 248 MouseEnter ............................................................................................. 40, 90 MouseLeave .................................................................................................. 40 MouseLeftButtonClic .................................................................................... 80 MouseLeftButtonDown ................................................................................. 40 MouseLeftButtonUp ...................................................................................... 40 MouseMouve ................................................................................................ 90 MouseMove .................................................................................................. 40 MultiScaleImage .................................................................................. 279, 289 MySQL ....................................................................................................... 124 MySqlConnection ........................................................................................ 125 MySqlDataReader ....................................................................................... 125
N
Name ............................................................................................................ 38 Namespace .................................................................................................. 225
O
Objects LINQ ........................................................................................................ 126 Timeline .................................................................................................... 106 ObjectDataSource ........................................................................................ 193
321
INDEX
ODP.NET .................................................................................................... 120 OneWay ...................................................................................................... 218 Oracle ......................................................................................................... 120 OracleConnection ........................................................................................ 121 OracleDataReader ........................................................................................ 122 Orientation .................................................................................................... 31
P
Password ....................................................................................................... 47 PasswordBox ................................................................................................. 47 PasswordChar ............................................................................................... 47 Path ............................................................................................................. 230 Pause ........................................................................................................... 239 Photoshop ..................................................................................................... 98 Plateforme.NET ........................................................................................... 181 Play ............................................................................................................. 239 Plein cran .................................................................................................. 242 Popup ....................................................................................................... 53-54 Postback ...................................................................................................... 197 ProgressBar ................................................................................................... 37 Property ...................................................................................................... 222 PropertyMetadata ........................................................................................ 229 Provider ...................................................................................................... 127 Python ......................................................................................................... 292
R
RadialGradientBrush ..................................................................................... 76 RadioButton .................................................................................................. 45 RadiusX ........................................................................................................ 52 RadiusY ........................................................................................................ 52 RangeValidator ............................................................................................ 192 RatioValueConverter ...................................................................................... 70
322
INDEX
Rectangle ...................................................................................................... 52 Register ....................................................................................................... 229 RegularExpressionValidator ......................................................................... 193 RepeatBehavior ............................................................................................. 82 Repeater .............................................................................................. 188, 194 RequiredFieldValidator ................................................................................ 192 Ressources .................................................................................................... 64 RIA ............................................................................................................... 98 RowDenition ............................................................................................... 28 RSS ..................................................................................................... 170, 174 Ruby ........................................................................................................... 292
S
ScrollViewer ................................................................................................. 32 SELECT ...................................................................................................... 116 SelectedDate ............................................................................................... 249 SelectedDateChanged .................................................................................. 249 SelectedItemChanged ............................................................................... 49-50 SelectionChanged ........................................................................................ 252 SGBD ......................................................................................................... 114 Silverlight ..................................................................................... 97, 201, 207 3 ............................................................................................................... 312 pour application mobile ........................................................................... 312 Slider ............................................................................................................ 51 SmallChange ................................................................................................. 51 Soap ............................................................................................................ 162 Source ......................................................................................................... 241 SQL ...................................................................................................... 115-116 SQL Server ................................................................................................. 114 SQLDataSource ........................................................................................... 193 StackPanel .................................................................................................... 30 StartPoint ...................................................................................................... 76 StaticResource ............................................................................................... 65 Stoke ............................................................................................................. 74
323
INDEX
StoryBoard .................................................................................................... 79 StoryBoard.TagetName .................................................................................. 82 StoryBoard.TargetProperty ............................................................................. 82 Style ............................................................................................................ 220 System.Windows.Controls ........................................................................... 246 System.Windows.Controls.Data ................................................................... 253
T
TabControl .................................................................................................. 252 TabItem ....................................................................................................... 252 TargetType .................................................................................................. 222 Template ....................................................................................... 61, 223, 264 TemplateBinding ................................................................................. 223, 230 Text .......................................................................................................... 46-47 TextBlock ...................................................................................................... 36 TextBox ........................................................................................................ 46 TextChanged ................................................................................................. 46 TextWrapping ................................................................................................ 37 ToggleButton ................................................................................................. 43 ToString ........................................................................................................ 60 TreeView ..................................................................................................... 195 TwoWay ...................................................................................................... 218
U
UnChecked ........................................................................................... 43 45 UPDATE ..................................................................................................... 116 URI ............................................................................................................... 35
V
Value ....................................................................................................... 37, 51 ValueChanged ............................................................................................... 51
324
INDEX
ValueConverter ........................................................................................ 66, 70 VerticalScrollBarVisibility ............................................................................. 33 ViewState .................................................................................................... 197 Virtual Earth ............................................................................................... 288 Visible ................................................................................................... 33, 244 Visual Source Safe ...................................................................................... 109 Visual Studio 2008 .............................................................................. 109, 183
W
WCF ........................................................................................................... 135 WeatherBugWebServiceSoapClient .............................................................. 162 Web.cong .................................................................................................. 190 Webographie ................................................................................................ 311 Widget ........................................................................................................ 153 Width ............................................................................................................ 29 Wrap ............................................................................................................. 37 WrapPanel ..................................................................................................... 31
X
XAML ..................................................................................................... 23-24 XML ............................................................................................................. 24 LINQ ........................................................................................................ 129 XMLDataSource ......................................................................................... 193
Y
Year ............................................................................................................ 248
325
Notes
Notes
Notes
Notes
Notes
Notes
Notes
Notes
Notes
Notes