Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
2006 Micro Application 20-22, rue des Petits-Htels 75010 Paris 1re dition - Septembre 2006
Jean-Alain BAEYENS 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). 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 responsable de toute omission, erreur ou lacune qui aurait pu se glisser dans ce produit 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 fin de dsignation des produits en tant que noms de ces derniers. ISBN : 2-7429-6729-X Couverture ralise par Room22. MICRO APPLICATION 20-22, rue des Petits-Htels 75010 PARIS Tl. : 01 53 34 20 20 Fax : 01 53 34 20 00 http://www.microapp.com Support technique galement disponible sur 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 fiche produit.
7729
Avant-propos
Le collection Guide du codeur sadresse aux personnes inities la programmation qui souhaitent dcouvrir une technologie particulire. Sans ngliger les aspects thoriques, nous donnons toujours priorit la pratique an que vous puissiez rapidement tre autonome. Avant dentrer dans le vif du sujet, notez ces quelques informations gnrales propos de la collection.
Conventions typographiques
An de faciliter la comprhension de 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.
: dans les programmes, indique un retour la ligne d aux contraintes de la mise en page.
Met laccent sur un point important, souvent dordre technique quil ne faut ngliger aucun prix.
Sommaire 1 Introduction . . . . . . . . . . . . . . . . . . . . . . 11
1.1. 1.2. 1.3. Avertissement . . . . . . Prrequis . . . . . . . . . Prsentation de XAML Quest-ce que XAML ? . Petits rappels XML . . . Les principes gnraux . Utiliser XAMLPad . . . Checklist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 13 13 14 15 17 19
1.4. 1.5.
Fonctionnalits de base . . . . . . . . . . . . . . . 21
2.1. Afficher du texte . Avec un Label . . . Avec un TextBlock . Introduire du texte Crer un bouton . Afficher un cadre . Afficher une image Checklist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 22 30 38 46 47 48 53
Sommaire
4.7. 4.8. 4.9. 4.10. 4.11. 4.12. 4.13. Crer un bouton automatique . . . Utiliser un Slider . . . . . . . . . . Utiliser un Expander . . . . . . . . Utiliser une ViewBox . . . . . . . . Utiliser un Popup . . . . . . . . . . Ajouter de la vido dans la fentre Checklist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 114 118 121 123 126 129
6.2. 6.3.
6.4.
Sommaire
7.2. 7.3. 7.4. Lier les donnes un objet mtier . . . . . . . . . . . . . . . 203 Lier les donnes sans utiliser le code .NET . . . . . . . . . . 207 Checklist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
8.4.
10
11
Le dessin . . . . . . . . . . . . . . . . . . . . . . . 315
11.1. Le dessin en 2D . . . . . . . . . . . . . . . . . . . . . . . . . . 316 11.2. Le dessin en 3D . . . . . . . . . . . . . . . . . . . . . . . . . . 323 11.3. Checklist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
12
13
Annexes . . . . . . . . . . . . . . . . . . . . . . . . 351
13.1. XAML sur le Web . . . . . . . . . . . . . . . . . . . . . . . . 352
Sommaire
13.2. Glossaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3. Schma dhritage des diffrentes classes Visual . . . . Schma dhritage des diffrentes classes Visual . . . . . Le dtail de lhritage dans la branche Control. . . . . . . Schma dhritage des diffrentes classes ContentElement Schma dhritage des diffrentes classes Freezable . . . 13.4. Rsum des classes et des attributs utiliss . . . . . . . Classe ArcSegment . . . . . . . . . . . . . . . . . . . . . Classe BezierSegment . . . . . . . . . . . . . . . . . . . . Classe Border . . . . . . . . . . . . . . . . . . . . . . . . . Classe Button . . . . . . . . . . . . . . . . . . . . . . . . . Classe Canvas . . . . . . . . . . . . . . . . . . . . . . . . Classe CheckBox . . . . . . . . . . . . . . . . . . . . . . Classe ColorAnimation . . . . . . . . . . . . . . . . . . . Classe ComboBox . . . . . . . . . . . . . . . . . . . . . . Classe DiffuseMaterial . . . . . . . . . . . . . . . . . . . . Classe DirectionalLight . . . . . . . . . . . . . . . . . . . Classe DockPanel . . . . . . . . . . . . . . . . . . . . . . Classe DocumentViewer . . . . . . . . . . . . . . . . . . . Classe DoubleAnimation . . . . . . . . . . . . . . . . . . Classe DoubleAnimationUsingKeyFrames . . . . . . . . Classe Ellipse . . . . . . . . . . . . . . . . . . . . . . . . . Classe EventTrigger . . . . . . . . . . . . . . . . . . . . . Classe Expander . . . . . . . . . . . . . . . . . . . . . . . Classe Figure . . . . . . . . . . . . . . . . . . . . . . . . . Classe FixedPage . . . . . . . . . . . . . . . . . . . . . . Classe FixedDocument . . . . . . . . . . . . . . . . . . . Classe Floater . . . . . . . . . . . . . . . . . . . . . . . . Classe FlowDocument . . . . . . . . . . . . . . . . . . . . Classe GradientStop . . . . . . . . . . . . . . . . . . . . . Classe Grid . . . . . . . . . . . . . . . . . . . . . . . . . . Classe GridSplitter . . . . . . . . . . . . . . . . . . . . . . Classe GridView . . . . . . . . . . . . . . . . . . . . . . . Classe GridViewColumn . . . . . . . . . . . . . . . . . . Classe Hyperlink . . . . . . . . . . . . . . . . . . . . . . . Classe Image . . . . . . . . . . . . . . . . . . . . . . . . . Classe ImageBrush . . . . . . . . . . . . . . . . . . . . . . Classe Label . . . . . . . . . . . . . . . . . . . . . . . . . Classe Line . . . . . . . . . . . . . . . . . . . . . . . . . . Classe LinearGradientBrush . . . . . . . . . . . . . . . . Classe LineSegment . . . . . . . . . . . . . . . . . . . . . Classe ListBox . . . . . . . . . . . . . . . . . . . . . . . . Classe ListView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 363 363 364 366 366 368 368 368 368 369 370 371 373 373 374 374 375 375 376 376 376 377 377 377 378 379 379 380 380 380 381 382 382 382 383 383 384 385 385 385 386 387
Sommaire
Classe Menu . . . . . . . . . . Classe MenuItem . . . . . . . . Classe MeshGeometry3D . . . Classe NavigationWindow . . Classe ObjectDataProvider . . Classe Page . . . . . . . . . . . Classe PageContent . . . . . . Classe Paragraph . . . . . . . . Classe Path . . . . . . . . . . . Classe PathFigure . . . . . . . Classe Pen . . . . . . . . . . . Classe PerspectiveCamera . . . Classe Polygon . . . . . . . . . Classe Polyline . . . . . . . . . Classe PolylineSegment . . . . Classe Popup . . . . . . . . . . Classe RadialGradientBrush . Classe RadioButton . . . . . . Classe Rectangle . . . . . . . . Classe RotateTransform . . . . Classe RepeatButton . . . . . . Classe ScaleTransform . . . . Classe ScrollViewer . . . . . . Classe Section . . . . . . . . . Classe Setter . . . . . . . . . . Classe SkewTransform . . . . Classe Slider . . . . . . . . . . Classe SolidColorBrush . . . . Classe SplineDoubleKeyFrame Classe StackPanel . . . . . . . Classe StoryBoard . . . . . . . Classe Style . . . . . . . . . . . Classe Table . . . . . . . . . . Classe TableCell . . . . . . . . Classe TableColumn . . . . . . Classe TableRow . . . . . . . . Classe TabControl . . . . . . . Classe TabItem . . . . . . . . . Classe TextBlock . . . . . . . . Classe TextBox . . . . . . . . . Classe Toolbar . . . . . . . . . Classe ToolbarTray . . . . . . Classe TranslateTransform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 387 388 388 389 389 390 391 392 392 392 393 393 393 393 394 394 394 395 396 396 396 396 397 397 397 398 399 399 399 400 400 401 401 401 401 401 402 403 404 405 405 406
Sommaire
Classe TreeView . . . . . . . . . . . . . . . . . . . . . . Classe TreeViewItem . . . . . . . . . . . . . . . . . . . Classe Trigger . . . . . . . . . . . . . . . . . . . . . . . Classe ViewBox . . . . . . . . . . . . . . . . . . . . . . Classe Viewport3D . . . . . . . . . . . . . . . . . . . . Classe Window . . . . . . . . . . . . . . . . . . . . . . . Classe WrapPanel . . . . . . . . . . . . . . . . . . . . . Classe XmlDataProvider . . . . . . . . . . . . . . . . . Classes autorises dans la zone internet . . . . . . . . Liste des touches de raccourcis pour les commandes ddition . . . . . . . . . . . . . . . . . . . . . . . . . . Liste des classes par catgories . . . . . . . . . . . . . Liste des couleurs prdnies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 406 406 407 407 408 409 409 409
14
Index . . . . . . . . . . . . . . . . . . . . . . . . . . 421
Ch apit re
1 Introduction
Avertissement ............................................. Prrequis ................................................... Prsentation de XAML ................................. Utiliser XAMLPad ....................................... Checklist ....................................................
12 12 13 17 19
Introduction
1.1 Avertissement
Ce livre vous fera dcouvrir progressivement XAML au moyen dexemples. Nous partirons des fonctionnalits les plus simples et les plus utiles pour aller vers des notions un peu plus complexes. Toutefois, an que vous puissiez facilement revenir par la suite sur une fonctionnalit particulire, les lments sont regroups le plus possible dans des chapitres ddis. la n du livre, vous trouverez un rcapitulatif des classes et des attributs utiliss. Celui-ci se veut non pas un rfrentiel complet mais plutt un rcapitulatif des notions vues. Il sagit dune prsentation du XAML et non de WinFX. Cest pourquoi nous nous attacherons principalement aux techniques accessibles depuis XAML, mme si certains moments nous devrons videmment voir ou raliser le code .NET associ. Au moment o ces lignes ont t crites, le code XAML et la bibliothque WinFX avec laquelle il travaille taient toujours en version bta et susceptibles dtre modis. Il se peut que certaines fonctionnalits aient entre-temps t ajoutes ou retires. Comme nous nous intresserons surtout aux fonctions les plus courantes, il est probable que le contenu de ce livre respecte les rgles en vigueur dans la version dnitive du produit.
1.2 Prrequis
Avant de pouvoir dvelopper avec XAML et WinFX, vous devez au pralable installer le Framework .NET 2.0 ainsi quune version de Visual Studio 2005. Vous pourriez utiliser nimporte quel diteur de texte, et ce y compris Notepad, mais lutilisation de Visual Studio vous facilitera grandement la vie, que ce soit pour la cration des projets ou la compilation de votre application. Il vous apporte galement lIntelliSense, ce qui est un trs gros avantage. Vous devez ensuite installer le kit de dveloppement WinFX. Attention, Windows XP SP2, Windows 2003 ou Windows Vista est requis pour pouvoir linstaller ! Pour raliser les exemples, nous utiliserons dune part "XAMLPad", un petit utilitaire livr avec le kit de dveloppement et dautre part "Microsoft Visual Basic 2005 Express Edition". An de bncier de toutes les fonctionnalits dans Visual Studio, vous devez galement installer lextension pour Visual Studio. Lensemble de ces lments sera repris dans le Framework 3.0, dont la sortie est attendue pour le dbut de lanne 2007.
12 Le guide du codeur
Prsentation de XAML
Windows Communication Fundation ; Windows Presentation Fundation ; Windows Workow Fundation ; Windows CardSpace ; .NET Framework 2.0.
XAML, quant lui, est un langage de description fond sur la norme XML. Contrairement au XML, les noms des balises et leur contenu doivent respecter une syntaxe stricte et correspondre une classe de WPF. Tout ce qui est fait en XAML peut galement tre fait dans du code traditionnel. De mme, XAML ne supporte quune partie du modle offert par WPF. Il offre en revanche une beaucoup plus grande lisibilit et une sparation entre le code logique et linterface graphique. Le XAML va nous permettre de dcrire les crans de lapplication. Le reste du traitement se fait de manire traditionnelle, via du code .NET. Dans le cadre de ce guide dinitiation, les parties .NET des exemples sont en Visual Basic .NET mais, si vous prfrez, vous pouvez bien entendu utiliser du C# ou nimporte quel autre langage .NET. Lapprentissage du .NET nest pas lobjectif de ce guide ; nanmoins, pour une bonne comprhension des exemples, il sera souvent ncessaire de voir aussi bien la partie XAML que la partie .NET. An de mieux comprendre la place de WinFX, de .NET et de XAML dans larchitecture, vous pouvez vous rfrer au schma ci-dessous.
Le guide du codeur 13
Introduction
Comme vous pouvez le constater, XAML, comme les langages .NET, forme la couche suprieure et reprsente linterface avec le dveloppeur. En dessous, nous retrouvons les couches composes de code manag ainsi que la CLR ncessaire pour lexcution de ce code. La dernire partie est la couche de communication avec Windows lui-mme. noter que WPF est pour sa part compos effectivement de Presentation Framework, de Presentation Core et de Milcore.
Un nud est tout ce qui se trouve entre une balise ouvrante <NomDuNoeud > et une balise fermante </ NomDuNoeud>. Les attributs sont des informations qui se placent dans la balise ouvrante.
<NomDuNoeud MonAttribut= "valeur">
Lattribut est toujours suivi du symbole = et dune valeur entre guillemets. Si le nud ne contient que des attributs, la syntaxe autorise de ne pas placer de balise fermante. La balise ouvrante se termine alors par le symbole /.
<NomDuNoeud MonAttribut= "valeur" />
Pour commenter du code XML, vous inclurez les commentaires dans une balise spcique.
<!-- votre commentaire -->
14 Le guide du codeur
Prsentation de XAML
permet dinstancier un objet de la classe Window. Si vous dsirez initialiser une proprit de la classe, il suffit dajouter un attribut dans le nud XML ou, selon les cas, de crer un nud enfant. Exemple :
<Window Title= "Titre" />
Cette balise permet dassigner la valeur "Titre" la proprit Titel de la classe Window. Notez que mme les proprits numriques doivent tre assignes comme une chane de caractres. Pour les valeurs boolennes, vous devez assigner True ou False entre guillemets. Pour les collections, il sagit de dnir des nuds enfants. Par exemple :
<Window> <Window.InputBindings> </Window.InputBindings> < /Window>
Le langage XAML est sensible la majuscule Vous devez respecter lcriture exacte dnie dans la documentation, et cela mme si votre projet est en Visual Basic. Ncrivez donc pas WINDOW mais bien Window.
Comme en XAML les noms des attributs des balises XML correspondent aux noms des proprits de la classe associe, nous parlerons indistinctement dans ce livre dattribut ou de proprit.
Le guide du codeur 15
Introduction
Pour mieux comprendre cette notion de correspondance entre XAML et les langages .NET, sachez que les deux bouts de code ci-dessous ont la mme fonction. En XAML :
<Label Name="lblNom" Width="60" Height="20"> mon nom </Label>
En VB .NET :
Dim lblNom as new Label lblNom.Width = 60 lblNom.Height = 20 lblNom.Text = "mon nom"
Comme vous pouvez le constater, ce qui est fait en XAML peut parfaitement tre fait en code .NET. Toutefois, la bonne pratique veut que lon utilise XAML pour dcrire linterface et les langages .NET traditionnels pour les traitements. Pour une mme classe, vous aurez alors vraisemblablement deux chiers de sources, un en XAML et lautre en code .NET. Les deux seront fusionns lors de la compilation. Nous reviendrons sur les diffrents chiers automatiquement gnrs ou non au cours de ce livre, au fur et mesure des besoins et de lexplication des diffrentes notions. Sachez toutefois que du code XAML seul peut dj tre compris par le systme et interprt sans mme devoir utiliser un compilateur. Cest par ce genre de code que nous allons commencer. XAML contient malgr tout quelques petites subtilits que nous allons dtailler. Tout dabord, le code XAML doit contenir un lment root comme le veut XML, mais cet lment doit tre un lment faisant partie du modle dapplication comme Window ou Page ou encore un conteneur tel Grid ou StackPanel. Nous reviendrons ultrieurement sur la notion de conteneur et dlments dapplication. Cet lment root doit contenir comme attribut la dclaration de deux Namespaces au minimum. Cette dclaration se fait en utilisant lattribut classique xmlns.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
Sil est ncessaire de faire rfrence dautres namespaces, il sera ncessaire dajouter dautres attributs xmlns en respectant la syntaxe ci-dessous.
16 Le guide du codeur
Utiliser XAMLPad
Lassembly peut tre omis si le namespace est contenu dans le mme assembly que le programme. XAML autorise galement lutilisation dattributs particuliers, dont voici les principaux.
Attributs spciques Attribut Utilit
x:Name
Cet attribut a la mme fonction que lattribut Name, qui est gnralement prsent. Ils sont totalement interchangeables mais ne peuvent tre utiliss simultanment. Prfrez Name x:Name et limitez lusage de ce dernier aux objets qui ne disposent pas de la proprit Name. Est encore un moyen de donner un nom mais, typiquement, ce type de nommage est utilis pour nommer des ressources. Il ne sagit en aucun cas du mme usage que x:Name. Attribut plac dans llment root ; il fait le lien avec la classe dnie dans le code behind (.NET). Permet de spcier dautres modieurs que partial et public, qui sont les valeurs par dfaut. Pour dnir une valeur nulle une proprit. Permet dintroduire du code .NET dans le chier XAML. Il sera gnralement utilis en conjonction avec CDATA :
<x:Code> <![CDATA[ Code ]]> </x:Code>
x:Key
Pour accder une valeur statique dune classe. Dans XAML, il a le mme effet que TypeOf dans le code .NET. Pour dterminer le type des arguments qui doivent tre reus. Cet attribut est principalement utilis par PageFunction. Permet dinstancier un array comme valeur dun attribut. Toutefois, il nest pas possible de remplir cet array dans le code XAML.
Ces diffrentes notions seront abordes par lexemple dans la suite de ce livre.
Introduction
XamlPad se prsente comme une fentre en deux parties. La partie suprieure affiche le rsultat du code et la partie infrieure, le code lui-mme.
En rsum, vous tapez le code en bas, il affiche le rsultat en haut. Cest aussi simple que cela. Pour faciliter la vision, vous disposez de quelques options :
j
Auto Parse, qui est active par dfaut et traite en temps rel votre code
Long code source Si votre code est long, vous pouvez dsactiver loption AutoParse. Cela vous vitera de dsagrables effets de rafrachissement.
j j
Avec les autres options de la barre doutils, vous pouvez changer la police utilise pour le code, choisir de cacher temporairement le code ou encore faire un zoom de la fentre daffichage du rsultat. Consultez la barre de statut, elle vous donne de prcieux renseignements sur votre code en cours de frappe.
18 Le guide du codeur
Checklist
Il est dommage que lIntelliSense ne soit pas disponible dans cet utilitaire. Si vous dsirez en disposer, vous pouvez reproduire les exemples dans Visual Studio. Mais vous devrez alors pralablement crer un projet spcique et demander chaque fois lexcution pour visualiser le rsultat. Vous pouvez vous reporter au chapitre Crer une application
Renvoi Windows page 132 pour vous aider crer votre projet.
1.5 Checklist
Les notions essentielles que nous avons vues dans ce premier chapitre sont :
j j j j
le matriel ncessaire pour dbuter en programmation XAML ; les bases du XML ; comment fonctionne XAML ; comment utiliser loutil XAMLPad.
Le guide du codeur 19
Ch apit re
2 Fonctionnalits de base
Afficher du texte .......................................... Introduire du texte ....................................... Crer un bouton .......................................... Afficher un cadre ......................................... Afficher une image ....................................... Checklist .................................................... 22 38 46 47 48 53
Fonctionnalits de base
Dans ce chapitre, nous allons voir de manire individuelle les diffrents lments de base ncessaires la ralisation dune interface utilisateur. Cela nous permettra daborder laffichage et la saisie de texte, laffichage dune image et lutilisation dun bouton. Avec ce minimum de connaissance, nous pourrons ensuite passer ltape suivante, qui sera le placement des lments. Cest seulement aprs que nous aborderons les autres contrles classiquement utiliss. Dans le but de grouper les fonctionnalits, nous ne nous contenterons pas de survoler ces fonctionnalits mais les verrons assez en profondeur.
Avec un Label
Le Label est probablement le contrle le plus utilis. Il reste trs simple manipuler mais, comme vous allez le constater, il nous rserve dagrables surprises. Pour crer un label, vous devez utiliser la balise du mme nom.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <Label> Mon premier label. </Label> </StackPanel> </Page>
Ne vous souciez pas pour linstant des balises Page et StackPanel. Nous verrons ultrieurement quoi elles servent et comment les utiliser. Sachez seulement que, sans la balise Page ou une autre balise racine valide, vous ne pourrez visualiser le rsultat. La balise StackPanel sert de conteneur. Nous reviendrons sur les conteneurs dans le chapitre Disposer les
Renvoi lments lcran sur la mise en page (page 56).
22 Le guide du codeur
Afficher du texte
Dans la suite, ces balises ne seront plus systmatiquement reprises au sein des exemples mais elles devront videmment tre prsentes.
Au lieu de placer le code entre la balise de dbut et la balise de n du nud Label, vous pouvez galement opter pour assigner lattribut Content. Le rsultat sera le mme. La syntaxe devient alors :
<Label Content="Mon premier label."/>
Porte des explications Les attributs que nous allons voir dans cette partie seront galement utilisables pour les autres contrles que nous aborderons ultrieurement.
Comme beaucoup de contrles, le Label occupe un espace rectangulaire. Nous pouvons nous en rendre compte en affichant un bord autour de notre contrle.
<Label BorderBrush="Chocolate" BorderThickness="1"> Mon premier label. </Label>
Les deux attributs sont ncessaires car aucune couleur nest dnie par dfaut et la taille est de zro.
Le guide du codeur 23
Fonctionnalits de base
La taille occupe dpend de divers paramtres comme la taille de la fentre. Si vous souhaitez contrler la taille de cette zone, vous pouvez utiliser les attributs Width et Height. Dans lexemple, nous allons xer la taille 200 pixels de large sur 60 pixels de haut.
<Label BorderBrush="Chocolate" BorderThickness="1" Width="200" Height="60"> Mon premier label. </Label>
24 Le guide du codeur
Afficher du texte
Centrage Notez au passage que par dfaut le contrle est centr horizontalement.
Ce nest pas le seul moyen de contrler la taille du Label. XAML met galement notre disposition les attributs MinWidth, MinHeight, MaxWidth et MaxHeight. Avec ces attributs, vous laissez la taille sadapter lenvironnement tout en xant des valeurs limites.
<Label BorderBrush="Chocolate" BorderThickness="1" MinWidth="100" MinHeight="30" MaxWidth="300" MaxHeight="80"> Mon premier label. </Label>
Si la position du texte ne vous convient pas, vous avez lopportunit de modier lalignement horizontal et vertical. Vous pouvez utiliser les attributs HorizontalContentAlignment et VerticalContentAlignment.
<Label BorderBrush="Chocolate" BorderThickness="1" Width="200" MinHeight="60" HorizontalContentAlignment="Center" VerticalContentAlignment="Bottom"> Mon premier label. </Label>
Le guide du codeur 25
Fonctionnalits de base
Les valeurs possibles sont respectivement Left, Rigth, Center, Stretch et Top pour lalignement horizontal et Bottom, Center et Stretch pour lalignement vertical.
Ne pas confondre Ne confondez pas ces deux attributs avec les attributs VerticalAlignment et HorizontalAlignment, qui permettent de centrer le contrle dans son conteneur.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Label BorderBrush="Chocolate" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center"> Mon premier label. </Label> </Page>
Absence de la balise StackPanel Pour une meilleure comprhension, dans cet exemple, la balise StackPanel a t retire. Cest pourquoi le code est prsent complet.
26 Le guide du codeur
Afficher du texte
Si la police par dfaut ne vous convient pas, vous disposez de cinq attributs diffrents pour ladapter votre got. Lattribut FontFamily permet de slectionner le type de police comme Arial ou Verdana. Lattribut FontSize dtermine la taille.
<Label HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Verdana" FontSize="14" FontWeight="Heavy" FontStyle="Italic" FontStretch="UltraExpanded"> Mon premier label. </Label>
Le guide du codeur 27
Fonctionnalits de base
Contrairement ce que nous connaissions avant, les possibilits sont bien plus tendues. FontStrech accepte pas moins de dix valeurs diffrentes allant de UltraCondensed UltraExpanded alors que FontWeight accepte quatorze valeurs allant de Thin Heavy. La taille du font peut varier de 1 35 791. En ce qui concerne les couleurs, nous disposons des attributs trs traditionnels Foreground et Background.
<Label HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Verdana" FontSize="14" FontWeight="Heavy" FontStyle="Italic" FontStretch="UltraExpanded" Foreground="Aquamarine" Background="Blue"> Mon premier label. </Label>
Nous avons vu les principales possibilits offertes avec le contrle Label et qui sont par ailleurs applicables aux autres contrles classiques que nous verrons dans ce chapitre.
Nommer ses contrles Pour pouvoir ultrieurement interagir avec les diffrents contrles que vous avez crs, ils doivent porter un nom. Bien que vous nayez pas interagir avec tous les contrles, je vous conseille de les nommer tous, et ce y compris les Label. Votre code sen trouvera beaucoup plus clair.
28 Le guide du codeur
Afficher du texte
Pour nommer le contrle, vous devez utiliser lattribut Name. Vous vous rendrez vite compte quil est utile dutiliser systmatiquement cet attribut.
<Label Name="lblPremierLabel" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Verdana" FontSize="14" FontWeight="Heavy" FontStyle="Italic" FontStretch="UltraExpanded" Foreground="Aquamarine" Background="Blue"> Mon premier label. </Label>
Donner toujours des noms clairs ses contrles La comprhension nale de votre programme sera grandement accrue si les noms donns sont clairs et sans ambigut. Si, sur le moment, cela vous parat superu, lors de modications ultrieures vous serez trs heureux de lavoir fait. Dans les exemples, en plus dun nom explicite, je commence par un prxe qui identie le type de contrle. Il existe dautres conventions de nommage, chacune ayant ses avantages et ses inconvnients. Choisissez-en une et tenez-vous-y.
signie que chaque mot dans le nom donn commence par une majuscule et que le reste du mot est en minuscule. Nom dun membre public
CamelCase suivi de _m. La bonne pratique veut que les membres publics soient vits. Prfrez un membre priv associ une proprit pour y accder. Ex. : NomDeRue_m CamelCase commenant par une minuscule et termin par _m. Ex. : nomDeRue_m CamelCase commenant par une majuscule. Si la proprit est associe un membre, le nom de la proprit sera le mme que le nom du membre associ mais sans le _m. Ex. : NomDeRue
Le guide du codeur 29
Fonctionnalits de base
camelCase commenant par une minuscule Si la proprit est associe un membre, le nom de la proprit sera le mme que le nom du membre associ mais sans le _m. Ex. : nomDeRue CamelCase commenant par une minuscule. Ex. : nomDeRue (en VB, vu que le langage est insensible aux majuscules, il sera probablement utile dajouter le suffixe _v pour viter la confusion avec la proprit) CamelCase termin par le type de contrle. Microsoft prconise maintenant que le type soit crit dans son entiret (TextBox et non Txt). Ex. : nomDeRueTextBox Comme dailleurs dans ce livre, vous trouverez souvent le type de contrle en prxe et non en suffixe. Toutefois, le fait de placer le type la n a lavantage de regrouper les lments concernant une mme donne dans lIntelliSense. La bonne pratique veut que les contrles soient privs. Si tel nest pas le cas, le nom doit commencer par une majuscule.
Nom de variable
Avec un TextBlock
Lorigine du TextBlock est plutt Web que Windows. Il fait pourtant son entre dans lAPI disponible pour les applications Windows classiques. Contrairement au contrle de type Label, TextBlock nhrite pas de la classe Control. TextBlock est optimis pour laffichage de longs textes. Je ne reviendrai pas sur la manire de modier les couleurs ou la police, il suffit dutiliser lidentique les techniques vues prcdemment. Le TextBlock ncessite un peu plus de mise en forme que le Label, qui se contente dun minimum. En effet, si nous utilisons la commande ci-dessous :
<TextBlock Name="blckTexte"> Nous sommes maintenant arrivs notre deuxime contrle. Comme vous avez dj pu le constater, XAML est la fois simple dutilisation et performant. </TextBlock>
30 Le guide du codeur
Afficher du texte
Il est possible de dterminer une taille la zone daffichage, et ainsi nous pouvons demander un arrangement automatique du texte.
<TextBlock Name="blckTexte" MaxWidth="200" MaxHeight="70" TextWrapping="Wrap"> Nous sommes maintenant arrivs notre deuxime contrle Comme vous avez dj pu le constater, XAML est la fois simple dutilisation et performant. </TextBlock>
Le guide du codeur 31
Fonctionnalits de base
Limiter la taille au lieu de la xer Au lieu de xer la taille, choisissez de dlimiter une taille maximale. De cette manire, si nous rduisons la taille de la fentre, le texte sadapte au mieux aux modications.
Lattribut TextWrapping peut prendre les valeurs NoWrap, Wrap mais galement WrapWithOverflow. Dans ce dernier cas, la taille du contrle sera automatiquement agrandie si ncessaire, mme si vous avez dni une taille avec lattribut Height. Bien sr, si pour quelque motif que ce soit la zone rserve au TextBlock devient trop petite, le texte ne pourra plus tre entirement affich. Dans ce cas, lattribut TextTrimming nous permettra dinclure automatiquement les signalant ainsi lutilisateur que le texte est incomplet.
<TextBlock Name="blckTexte" MaxWidth="200" MaxHeight="70" TextWrapping="Wrap" TextTrimming="WordEllipsis"> Nous sommes maintenant arrivs notre deuxime contrle Comme vous avez dj pu le constater, XAML est la fois simple dutilisation et performant. </TextBlock>
32 Le guide du codeur
Afficher du texte
Lattribut TextTrimming, en plus de la valeur par dfaut (None), peut prendre deux valeurs diffrentes. Soit WordEllipsis, comme dans notre exemple, o larrt se fait aprs un mot entier, soit CharacterEllipsis, qui provoque larrt derrire nimporte quel caractre. Comme vous pouvez le constater, le contrle se place trs prs des bords de son conteneur, ce qui nest pas forcment du meilleur effet. Vous pouvez dnir une marge tout autour de votre contrle en utilisant lattribut Margin. Cet attribut nest pas spcique au TextBlock et nous aurions dj pu lutiliser avec le contrle de type Label.
<TextBlock Name="blckTexte" MaxWidth="200" MaxHeight="70" TextWrapping="Wrap" TextTrimming="WordEllipsis" Margin="5,5,5,5" > Nous sommes maintenant arrivs notre deuxime contrle. Comme vous avez dj pu le constater, XAML est la fois simple dutilisation et performant. </TextBlock>
Pour terminer les spcicits du TextBlock par rapport au Label, il nous reste voir lattribut TextAlignment. Les valeurs possibles sont les trs classiques Left, Right, Center et Justify.
<TextBlock Name="blckTexte" MaxWidth="200" MaxHeight="70" TextWrapping="Wrap" TextTrimming="WordEllipsis" Margin="5,5,5,5" TextAlignment="Justify" > Nous sommes maintenant arrivs notre deuxime contrle. Comme vous avez dj pu le constater, XAML est la fois simple dutilisation et performant. </TextBlock>
Le guide du codeur 33
Fonctionnalits de base
De plus, le TextBlock permet denrichir le contenu. Vous pouvez par exemple y inscrire du texte en gras, en italique ou soulign.
<TextBlock Name="blckTexte" MaxWidth="200" MaxHeight="70" TextWrapping="Wrap" TextTrimming="WordEllipsis" Margin="5,5,5,5" TextAlignment="Justify" > Nous sommes maintenant arrivs notre deuxime contrle Comme vous avez dj pu le constater, <Bold>XAML</Bold> est la fois <Underline>simple dutilisation</Underline> et <Italic>performant</Italic>. </TextBlock>
34 Le guide du codeur
Afficher du texte
Si ces possibilits denrichissement ne vous suffisent pas, vous pouvez utiliser TextDecoration. Cette proprit nest pas spcique TextBlock, et vous pouvez la retrouver quasiment partout o du texte est affich. Elle est accessible grce la balise TextBlock. TextDecorations, pour un autre contrle, remplace TextBlock par la valeur approprie. Elle permet dajouter des dcorations vos caractres. La description de la dcoration est dnie lintrieur du nud TextDecoration. La dcoration est en ralit un trait qui peut tre plac quatre endroits diffrents. La position est dnie au moyen de la proprit Location. Elle peut tre au-dessus du caractre, au milieu du caractre, sous le caractre ou juste sous le caractre. La taille, la couleur, la forme du trait sont dnies avec un objet de type Pen. Ci-dessous, vous trouverez un code complet reprenant les diffrentes possibilits numres ci-avant.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <TextBlock TextWrapping="WrapWithOverflow" Margin="5,5,5,5" Width="800" HorizontalAlignment="Center"> <Bold>Non seulement vous pouvez utiliser lenrichissement classique</Bold> mais vous pouvez aussi utiliser un enrichissement plus complexe <LineBreak/>
Le TextBlock suivant utilise une dcoration au milieu du caractre. Le trait est rouge et dune paisseur de 2 points.
<TextBlock> <TextBlock.TextDecorations> <TextDecoration Location="Strikethrough"> <TextDecoration.Pen> <Pen Brush="Red" Thickness="2"/> </TextDecoration.Pen> </TextDecoration> </TextBlock.TextDecorations> comme du barr color </TextBlock> <LineBreak/>
Le TextBlock suivant utilise une dcoration sous le caractre. Le trait est bleu et toujours dune paisseur de 2 points.
Le guide du codeur 35
Fonctionnalits de base
<TextBlock> <TextBlock.TextDecorations> <TextDecoration Location="Underline"> <TextDecoration.Pen> <Pen Brush="Blue" Thickness="2"/> </TextDecoration.Pen> </TextDecoration> </TextBlock.TextDecorations> comme un soulignement en bleu </TextBlock> <LineBreak/>
Le TextBlock suivant utilise une dcoration juste sous le caractre. Le trait est noir et dune paisseur de 1 point.
<TextBlock> <TextBlock.TextDecorations> <TextDecoration Location="Baseline"> <TextDecoration.Pen> <Pen Brush="Black" Thickness="1"/> </TextDecoration.Pen> </TextDecoration> </TextBlock.TextDecorations> comme une fine ligne sous les caractres </TextBlock> <LineBreak/>
Le TextBlock suivant utilise une dcoration au-dessus du caractre. Le trait est rouge et dune paisseur de 2 points.
<TextBlock> <TextBlock.TextDecorations> <TextDecoration Location="OverLine"> <TextDecoration.Pen> <Pen Brush="Red" Thickness="2"/> </TextDecoration.Pen> </TextDecoration> </TextBlock.TextDecorations> ou encore une ligne au dessus </TextBlock> <LineBreak/>
Le TextBlock suivant utilise plusieurs dcorations. Une premire juste sous le caractre. Le trait est rouge, dune paisseur de 1 point et discontinu. La seconde est sous le caractre. Le trait est bleu, dune paisseur de 1 point et est continu. Les deux ensembles ralisent un double trait spcique.
36 Le guide du codeur
Afficher du texte
<TextBlock> <TextBlock.TextDecorations> <TextDecoration Location="Baseline"> <TextDecoration.Pen> <Pen Brush ="Red" Thickness="1"> <Pen.DashStyle> <DashStyle Dashes="1"/> </Pen.DashStyle> </Pen> </TextDecoration.Pen> </TextDecoration> <TextDecoration Location="Underline"> <TextDecoration.Pen> <Pen Brush="Blue" Thickness="1"/> </TextDecoration.Pen> </TextDecoration> </TextBlock.TextDecorations> Bien sur vous pouvez mlanger ces options et utiliser </TextBlock> <LineBreak/>
Ce dernier TextBlock utilise une dcoration sous le caractre. Le trait est dune paisseur de 4 points et dun dgrad allant dun bleu lger un bleu fonc.
<TextBlock> <TextBlock.TextDecorations> <TextDecoration Location="Underline"> <TextDecoration.Pen> <Pen Thickness="4"> <Pen.Brush> <LinearGradientBrush> <LinearGradientBrush .GradientStops> <GradientStop Color="LightBlue" Offset="0"/> <GradientStop Color="DarkBlue" Offset="1"/> </LinearGradientBrush .GradientStops> </LinearGradientBrush> </Pen.Brush> </Pen> </TextDecoration.Pen> </TextDecoration> </TextBlock.TextDecorations> ou encore dutiliser des dgrads
Le guide du codeur 37
Fonctionnalits de base
</TextBlock> <LineBreak/> <LineBreak/> Les possibilits sont infinies ! </TextBlock> </StackPanel> </Page>
Notez au passage lutilisation de la balise LineBreak pour provoquer un passage ligne impos. Dans lexemple, vous aurez pu constater la prsence dun dgrad ;
Renvoi si vous souhaitez en savoir plus sur cette fonctionnalit, elle est
38 Le guide du codeur
Introduire du texte
Nous pouvons appliquer ce contrle tout ce que nous avons dj vu pour le contrle Label.
Appliquer des marges Pour une question de lisibilit et de mise en page, je vous conseille dappliquer systmatiquement des marges vos contrles de type TextBox.
Le guide du codeur 39
Fonctionnalits de base
Lattribut MaxLength va nous permettre de limiter lencodage. Ce qui est bien pratique quand le contenu doit tre enregistr dans une base de donnes. Vous vitez ainsi une perte dinformation linsu de lutilisateur ou des problmes plus tard dans le code. Lattribut CharacterCasing limite lui aussi lencodage en imposant automatiquement le texte en majuscule (valeur Upper) ou en minuscule (valeur Lower). Jaurais galement apprci la possibilit de forcer la premire lettre en majuscule et les autres en minuscules mais, actuellement, ce nest pas prvu.
<TextBox Name="txtNom" Margin="3,3,3,3" MaxLength="20" CharacterCasing="Upper" />
Un TextBox peut galement tre multiligne. Dans ce cas, vous aurez la possibilit dajuster son utilisation avec les attributs AcceptsReturn, AcceptsTab et TextWrapping. Lattribut AcceptsReturn autorise ou non lutilisation du passage la ligne impos (touche [Entre]). Lattribut AcceptsTab autorise ou non lemploi de la tabulation.
Dplacement par tabulations Si vous autorisez lutilisation de la tabulation, elle ne pourra videmment plus tre utilise pour passer au champ suivant. Toutefois, mais il faut le savoir, la combinaison [Ctrl]+[Tab] remplit aussi cette fonction.
40 Le guide du codeur
Introduire du texte
Lattribut TextWrapping dtermine le comportement du contrle quand le texte frapp arrive en bout de ligne. Les valeurs possibles sont NoWrap, Wrap et WrapWithOverflow. Cette dernire va non seulement provoquer un passage la ligne automatique mais, contrairement Wrap, galement tendre vers le bas la zone prvue initialement.
<TextBox Name="txtNom" Margin="3,3,3,3" MinHeight="80" AcceptsReturn="True" AcceptsTab="True" TextWrapping="WrapWithOverflow" />
Dans lexemple ci-dessus, le texte arrive sur la dernire ligne. Si daventure nous continuons la frappe, vous pouvez constater leffet de WrapWithOverflow.
Le guide du codeur 41
Fonctionnalits de base
Combiner la zone de dbordement et la hauteur maximale Si vous utilisez loption WrapWithOverflow, il est prfrable de xer une taille maximale en utilisant lattribut MaxHeight.
Gestion des lignes Comme vous pouvez le remarquer, rien nindique quil sagisse ou non dun
Les attributs MinLines et MaxLines sont une bonne alternative lutilisation des attributs MinHeight et MaxHeight. MinLines et MaxLines xent respectivement le nombre minimal et maximal de lignes visibles. La taille sera automatiquement adapte en fonction. De cette faon, la dernire ligne visible sera toujours complte, ce qui nest pas le cas en xant les limites de la hauteur en nombre de points.
<TextBox Name="txtNom" Margin="3,3,3,3" MinLines="2" MaxLines="3" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap" />
Selon les comportements que vous aurez dnis pour votre TextBox, lutilisateur sera oblig de faire dler le texte horizontalement et verticalement. Sans aide visuelle, il nest pas toujours ais pour lutilisateur de voir le texte cach. Le mieux dans ce cas est dajouter des barres de dlement. vous de choisir celle quil vous faut.
<TextBox Name="txtNom" Margin="3,3,3,3" MinLines="2" MaxLines="3" MaxWidth="300" AcceptsReturn="True" AcceptsTab="True" TextWrapping="NoWrap" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" />
42 Le guide du codeur
Introduire du texte
Les valeurs possibles pour les attributs VerticalScrollBarVisibility et HorizontalScrollBarVisibility sont Auto, Hidden, Disabled et Visible. Pour plus dinformations sur lutilisation des valeurs possibles, reportezRenvoi vous au paragraphe Autoriser le dlement page 77.
Conit entre hauteur et nombre de lignes Si vous utilisez simultanment les attributs MinLines, MaxLines et les attributs MinHeight, MaxHeight, ce sont ces derniers qui auront la prsance. MinLines et MaxLines nauront ds lors aucun effet.
Dans certaines circonstances, vous souhaiterez certainement afficher un TextBox mais sans autoriser lutilisateur en modier le contenu. Pour ce faire, vous disposez de deux possibilits, soit utiliser lattribut IsReadOnly, soit utiliser lattribut IsEnabled. Chacune de ces mthodes offre ses avantages et ses inconvnients. Voyons dabord leffet de IsReadOnly.
<TextBox Name="txtNom" Margin="3,3,3,3" Text="Ce texte est en lecture seule." IsReadOnly="True" />
Le guide du codeur 43
Fonctionnalits de base
Visuellement, il ny a aucune diffrence entre un TextBox limit la lecture et un autre TextBox. Toutefois, il ne vous sera pas possible dintroduire du texte dans ce contrle. En revanche, vous pourrez slectionner du texte pour faire un copier en vue de le coller ailleurs.
Valeur par dfaut Il est difficile de concevoir une TextBox non modiable sans valeur par dfaut. Pour donner cette valeur, vous devez utiliser lattribut Text.
En revanche, avec lattribut IsEnabled, lutilisateur visualise directement que le champ est inaccessible.
<TextBox Name="txtNom" Margin="3,3,3,3" Text="Ce texte est en lecture seule." IsEnabled="False" />
Cette technique a toutefois deux dfauts. Premirement, il nest pas possible de slectionner du texte en vue de le copier ailleurs. Deuximement, beaucoup dutilisateurs se plaignent du manque de lisibilit des TextBox dsactivs. Vous pouvez modier les attributs de couleur de votre TextBox pour quil affiche visuellement son tat soit en copiant le style dun TextBox dsactiv, soit en utilisant votre propre charte graphique.
44 Le guide du codeur
Introduire du texte
Dans cet exemple, le style du champ en lecture seule est proche du style du champ dsactiv tout en tant plus lisible.
<TextBox Name="txtNom" Margin="3,3,3,3" Text="Ce texte est en lecture seule." IsEnabled="False" /> <TextBox Name="txtNom2" Margin="3,3,3,3" Text="Ce contrle est en lecture seule." IsReadOnly="true" Foreground="Gray" Background="Beige" />
Le guide du codeur 45
Fonctionnalits de base
Introduire un mot de passe Si vous dsirez crer une zone de saisie pour introduire un mot de passe, utilisez la balise PasswordBox en lieu et place de TextBox. Il ny a pas de diffrence majeure dans leur utilisation si ce nest que les caractres affichs sont remplacs par des * et que la proprit Text est remplace par la proprit Password.
46 Le guide du codeur
Afficher un cadre
Fixer la taille des boutons Gnralement, la taille des boutons prsents dans un mme cran est xe. Ne pas respecter cette rgle produit le plus souvent un trs mauvais effet visuel.
De manire gnrale, le bouton OK sera prsent comme bouton par dfaut. De mme manire, le bouton Annuler devrait tre associ la touche [Echap]. Pour quun bouton soit le bouton par dfaut, il suffit dutiliser lattribut IsDefault. Pour associer un bouton la touche [Echap], il suffit dutiliser lattribut IsCancel.
<Button Name="btnOk" IsDefault="True" Width="80" Height="30" > Ok </Button> <Button Name="btnCancel" Content="Annuler" Width="80" Height="30" IsCancel="True"/>
Nous devons encore pouvoir associer le bouton avec une action bien dnie. Toutefois, cette opration faisant appel du code .NET, nous reviendrons dessus dans le chapitre sur les vnements (page 138).
Fonctionnalits de base
48 Le guide du codeur
Erreur dans le code Le contenu de la balise Image est volontairement scind en deux lignes pour une question de lisibilit de lexemple. Toutefois, si vous dsirez le reproduire, il sera ncessaire de regrouper le chemin du chier sur une mme ligne.
Le nud ls ImageSource permet de dnir le chier qui sera affich. Les formats supports sont bmp, gif, ico, jpg, png et tiff. Vous pouvez galement xer les dimensions de limage avec les diffrents attributs MinWidth, MaxWidth, MinHeight, MaxHeight ou encore, comme dans lexemple ci-dessous, en faire une miniature en utilisant les attributs Width et Height.
<Image Name="imgPhoto" Width="100" Height="100" > <Image.Source> C:\Documents and Settings\All Users\Documents\ Mes images\chantillons dimages\Hiver.jpg </Image.Source> </Image>
Le guide du codeur 49
Fonctionnalits de base
Il existe une seconde possibilit pour afficher des images mais il sagit alors non pas directement dun contrle placer dans votre page mais dune image utilise dans un contrle ; par exemple insrer limage comme fond dun bouton, dun cadre ou dune page.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Page.Background> <ImageBrush ImageSource="\Emoticons\no.gif" /> </Page.Background> <StackPanel> <Label> Une fentre avec une image de fond </Label> </StackPanel> </Page>
50 Le guide du codeur
ImageBrush dispose dattributs tout fait particuliers pour grer lapparence de limage. Il nest pas question de taille puisque celle-ci dpend du conteneur. En revanche, il est toutefois possible de contrler la taille relative en utilisant lattribut Viewport. Si vous lassociez TileMode, vous pouvez par exemple crer une mosaque.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Page.Background> <ImageBrush Viewport="0.5,0.5,0.5,0.5" TileMode="TILE" ImageSource="\Emoticons\no.gif" /> </Page.Background> <StackPanel> <Label> Une fentre avec une image de fond </Label> </StackPanel> </Page>
Le guide du codeur 51
Fonctionnalits de base
Il est aussi possible de paramtrer ltirement de limage et son alignement en utilisant les attributs Stretch, AlignmentX.et AlignmentY.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Page.Background> <ImageBrush Stretch="None" AlignmentY="Bottom" AlignmentX="Right" ImageSource="\Emoticons\no.gif" /> </Page.Background> <StackPanel> <Label> Une fentre avec une image de fond </Label> </StackPanel> </Page>
52 Le guide du codeur
Checklist
2.6 Checklist
Voici les points essentiels que nous avons abords dans ce chapitre :
j j j j j j j
laffichage des textes et leurs manipulations avec des Label et TextBlock ; laffichage et la saisie des textes avec TextBox ; la saisie dun mot de passe avec PasswordBox ; laffichage des boutons avec Button ; laffichage des images avec Image et ImageBrush ; la ralisation de cadres avec Border ; lutilisation des attributs les plus communs et utilisables avec la majorit des contrles ; lutilisation des dcorateurs avec TextDecoration.
Le guide du codeur 53
Ch apit re
Avec les contrles vus au chapitre prcdent, nous possdons assez dlments pour raliser un cran complet et complexe. Ce qui nous manque maintenant, cest une mthode pour organiser tout cela. XAML ne se contente pas dune mthode mais nous en fournit plusieurs, chacune ayant ses avantages et ses inconvnients.
<TextBox Name="txtCP" Canvas.Top="70" Canvas.Left="80" Width="50" MaxLength="5"/> <Label Name="lblLocalite" Canvas.Top="70" Canvas.Left="150"> Localit </Label> <TextBox Name="txtLocalite" Canvas.Top="70" Canvas.Left="200" Width="230" MaxLength="50"/> </Canvas> </Page>
Comme vous pouvez le constater, le placement lcran se fait au moyen des attributs Canvas.Top et Canvas.Left. Il sagit de proprits attaches. Une proprit attache est en fait une proprit du parent, ici du Canvas, mais pour laquelle chaque enfant peut assigner une valeur diffrente. Cest pourquoi, bien que proprit de Canvas, lattribut Canvas.Top est par exemple un attribut des lments contenus dans le Canvas et non du Canvas lui-mme. La balise Canvas dispose elle-mme de quelques attributs. Lattribut Background vous permet de changer la couleur du fond si la couleur standard ne vous satisfait pas.
<Canvas Background="LightCoral">
Le guide du codeur 57
Un autre attribut intressant est lattribut IsEnabled. En effet, si vous lui assignez la valeur False, lensemble des contrles contenus dans le Canvas seront eux aussi dsactivs.
Dsactiv et non lecture seule Noubliez pas toutefois les diffrences que nous avons vues prcdemment entre dsactiver et lecture seule pour un contrle tel que la bote de texte.
58 Le guide du codeur
Les attributs Canvas.Top et Canvas.Left ne sont pas les seuls utilisables pour positionner un contrle. Vous pouvez galement utiliser Canvas.Right et Canvas.Bottom, ce qui permet de placer un contrle relativement nimporte quel coin du Canvas. Ajoutons le code suivant devant la balise de n du nud Canvas.
<Border Width="100" Height="120" BorderThickness="1" Background="White" BorderBrush="Black" Canvas.Top="10" Canvas.Right="10"> <TextBlock Name="blkPhoto" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"> Photo </TextBlock> </Border> <Label Name="lblCopyright" Canvas.Bottom="10" Canvas.Right="10" Content="Micro Application 2006" />
Le guide du codeur 59
Comme vous pouvez le constater, le fait de positionner un contrle non pas partir du coin suprieur gauche mais dun autre coin ne fait pas que changer le systme de coordonnes. Lors du redimensionnement de lcran, les contrles suivent le coin partir duquel ils sont positionns. Cette facult pourra tre utilise dans de nombreuses circonstances pour obtenir un cran beaucoup plus exible.
Fixer une taille minimale son Canvas Si vous ne xez pas une taille minimale votre Canvas, les lments contenus vont invitablement se chevaucher si la fentre est rduite au-del de la taille critique.
En remplaant la balise Canvas dans lexemple par celle ci-dessous, nous empcherons ce comportement chaotique.
<Canvas Background="LightBlue" MinWidth="550" MinHeight="200">
60 Le guide du codeur
La premire chose faire lorsque lon utilise une grille, cest de dnir les lignes et les colonnes.
<Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions>
Nous pouvons ensuite utiliser les contrles tout en dnissant leurs positions dans la grille en utilisant Grid.Row et Grid.Column.
<Label Name="lblNom" Grid.Row="0" Grid.Column="0"> Nom </Label> <TextBox Name="txtNom" Grid.Row="0" Grid.Column="1" MaxLength="30" CharacterCasing="Upper" /> <Label Name="lblPrenom" Grid.Row="0" Grid.Column="2">
Le guide du codeur 61
Prnom </Label> <TextBox Name="txtPrenom" Grid.Row="0" Grid.Column="3" MaxLength="30"/> <Label Name="lblAdr" Grid.Row="1" Grid.Column="0"> Rue </Label> <TextBox Name="txtAdr" Grid.Row="1" Grid.Column="1" MaxLength="80"/> <Label Name="lblCP" Grid.Row="2" Grid.Column="0"> Code postal </Label> <TextBox Name="txtCP" Grid.Row="2" Grid.Column="1" MaxLength="5"/> <Label Name="lblLocalite" Grid.Row="2" Grid.Column="2" > Localit </Label> <TextBox Name="txtLocalite" Grid.Row="2" Grid.Column="3" MaxLength="50"/> <Border BorderThickness="1" Background="White" Grid.Row="0" Grid.Column="4" BorderBrush="Black"> <TextBlock Name="blkPhoto" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"> Photo </TextBlock> </Border> <Label Name="lblCopyright" Content="Micro Application 2006" Grid.Row="3" Grid.Column="4"/> </Grid> </Page>
Comme vous pouvez le constater, la dnition de la grille se fait au dbut en utilisant les collections RowDefinitions et ColumnDefinitions. Ces collections contiennent autant dlments que de lignes ou de colonnes dsires. la place des attributs Canvas.Top et autre Canvas.Left, ce sont les attributs Grid.Column et Grid.Row.
Dbut de numrotation La numrotation des lignes et des colonnes commence 0. La ligne 1 est donc bel et bien la seconde ligne.
Malheureusement, comme vous pouvez le voir ci-dessous, le rsultat obtenu nest pas vraiment la hauteur des esprances.
62 Le guide du codeur
Commenons par le plus simple, le fond dcran nest pas color. Pour cela, pas de soucis, il suffit dutiliser le mme attribut que pour Canvas.
<Grid Background="LightBlue">
Autre problme vident, la zone de saisie de ladresse est limite la deuxime colonne. Pour rsoudre ce problme, il est possible dtendre le contrle sur plusieurs colonnes en utilisant lattribut Grid.ColumnSpan.
<TextBox Name="txtAdr" Grid.Row="1" Grid.Column="1" MaxLength="80" Grid.ColumnSpan="3"/>
Il en va de mme pour la zone photo qui est limite une ligne. La solution est quasiment identique except que lattribut est Grid.RowSpan.
<Border BorderThickness="1" Background="White" Grid.Row="0" Grid.Column="4" Grid.RowSpan="3" BorderBrush="Black"> <TextBlock Name="blkPhoto" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"> Photo </TextBlock> </Border>
Le guide du codeur 63
Avec lajout de ces nouveaux attributs, lcran est enn un peu plus ressemblant.
Le code ainsi modi va permettre de placer le copyright en bas droite de lcran, et ce quelle que soit sa dimension comme ctait le cas avec le canevas. Placez galement lattribut ci-dessous dans chaque balise TextBox et dans la balise Border.
Margin="2,2,2,2"
Le gros problme restant est llargissement inconsidr des botes de texte, qui dnature fortement leffet visuel de lcran. Pour y remdier, il suffit dassigner les attributs MaxHeight et VerticalAlignment chaque TextBox.
64 Le guide du codeur
Pour contrler le comportement de la fentre en cas de redimensionnement, vous pouvez ajuster les dimensions des lignes et des colonnes. Nhsitez pas utiliser les dimensions minimales et maximales.
<Grid.ColumnDefinitions> <ColumnDefinition Width="70"/> <ColumnDefinition MinWidth="60"/> <ColumnDefinition Width="50"/> <ColumnDefinition MinWidth="60"/> <ColumnDefinition MinWidth="120" MaxWidth="200"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition MinHeight="22"/> <RowDefinition MinHeight="22"/> <RowDefinition MinHeight="76"/> <RowDefinition MinHeight="20"/> </Grid.RowDefinitions>
Redimensionnez la fentre et voyez ce qui se passe. Bien sr, comme pour Canvas, vous pouvez utiliser lattribut IsEnabled pour dsactiver lensemble de la grille.
Visualiser la grille Parfois, pour faciliter la mise en page, il est intressant de voir les limites des cellules. Pour cela, utilisez lattribut ShowGridLines.
Le guide du codeur 65
En complment de ces possibilits, XAML offre la possibilit de crer des bords mobiles pour permettre lutilisateur dajuster la taille que ce soit en largeur ou en hauteur. Cette possibilit doit tre mise en uvre en utilisant un GridSplitter. Cette balise va vous permettre de dnir dans la grille sur quelle cellule ou groupe de cellules vous dsirez placer la bordure mobile et dans quel sens. An de vous montrer cette fonctionnalit, nous allons construire un tableau de 3 lignes et 4 colonnes. La hauteur de la premire ligne pourra tre adapte ainsi que la largeur de la premire colonne. La premire partie du code est classique. Notez toutefois que 4 lignes et non 3 sont dnies. Nous reviendrons sur le pourquoi la n de lexercice. Ensuite, les 2 GridSplitter sont dnis. Le premier dans le sens vertical, via lattribut ResizeDirection= "Columns", lautre dans le sens horizontal avec ResizeDirection= "Rows". La position est donne respectivement avec Grid.Column et Grid.Row. ColSpan et RowSpan permettent dtendre la visibilit du bord sur lensemble des cellules.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="5"/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <GridSplitter Grid.Column="0" Grid.RowSpan="4" ResizeDirection="Columns" ShowsPreview="False"/> <GridSplitter Grid.Row="1" Grid.ColumnSpan="4" ResizeDirection="Rows" HorizontalAlignment="Stretch" ShowsPreview="True"/> </Grid> </Page>
66 Le guide du codeur
Lattribut ShowsPreview modie le comportement de telle sorte que, si vous souhaitez la prvisualisation, le bord ne bouge que quand vous lchez le bouton de la souris. Dans lintervalle, cest une ligne repre qui prvisualise la future position du bord.
4 lignes au lieu de 3 Maintenant, comme promis, pourquoi 4 et non 3 lignes. Comme vous avez pu le constater, la hauteur de la ligne a t xe 5. En fait, cette astuce est utilise pour pallier un comportement diffrent entre le bord horizontal et vertical. Cette diffrence aura probablement disparu dans la version dnitive et
Le guide du codeur 67
cette ligne supplmentaire naura plus lieu dtre mais, dans le doute, il vaut mieux savoir comment contourner le problme. Donc, si pour un bord vertical celui-ci se place correctement droite de la colonne, pour une ligne horizontale il napparat pas. En utilisant HorizontalAlignment= Stretch , le bord devient visible mais occupe toute la hauteur. Lide est donc dutiliser une ligne supplmentaire pour contenir le bord ainsi cr.
Les diffrents contrles doivent tre indiqus dans lordre dans lequel vous dsirez les voir apparatre. Ils sont affichs de gauche droite et de haut en bas.
<TextBlock Width="200" TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify"> <Bold>StackPanel</Bold> Lutilisation dun StackPanel offre encore des possibilits plus restreinte que le WrapPanel. Toutefois, contrairement au WrapPanel, il offre une structure moins mobile et donc beaucoup plus controlable. Dans un StackPanel, chaque contrle occupe une ligne. </TextBlock> <TextBlock Width="200" TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify">
68 Le guide du codeur
<Bold>Grid</Bold>: Cette mthode est gnralement la mthode la plus recommande car elle offre un trs haut niveau dadaptabilit du contenu de lcran sa taille et donc galement aux changements de rsolution. Elle est toutefois plus complexe mettre en uvre. </TextBlock> </WrapPanel> </Page>
Le guide du codeur 69
Les diffrents contrles doivent tre indiqus dans lordre dans lequel vous dsirez les voir apparatre. Ils sont affichs de haut en bas.
<TextBlock TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify"> <Bold>StackPanel</Bold> Lutilisation dun StackPanel offre encore des possibilits plus restreinte que le WrapPanel. Toutefois, contrairement au WrapPanel, il offre une structure moins mobile et donc beaucoup plus controlable. Dans un StackPanel, chaque contrle occupe une ligne. </TextBlock> <TextBlock TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify"> <Bold>Grid</Bold>: Cette mthode est gnralement la mthode la plus recommande car elle offre un trs haut niveau dadaptabilit du contenu de lcran sa taille et donc galement aux changements de rsolution. Elle est toutefois plus complexe mettre en uvre. </TextBlock> </StackPanel> </Page>
70 Le guide du codeur
Utiliser un empilement
Longueur de ligne Contrairement lexemple tel quil est dans le chapitre sur le WrapPanel, o nous avions dni la largeur avec la proprit Width, comme avec StackPanel les lments sont automatiquement placs lun sous lautre il nest pas ncessaire de xer la largeur.
Le guide du codeur 71
Utiliser le docking
<TextBlock TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify"> <Bold>Grid</Bold>: Cette mthode est gnralement La mthode la plus recommande car elle offre un trs haut niveau dadaptabilit du contenu de lcran sa taille et donc galement aux changements de rsolution. Elle est toutefois plus complexe mettre en uvre. </TextBlock> </Border> </DockPanel> </Page>
Tout dabord, des balises Border ont t ajoutes an de mieux visualiser le rsultat. Elles nont aucun but particulier si ce nest une meilleure comprhension du rsultat. Du fait de leur prsence, la taille des diffrents blocs est xe dans les balises Border et non plus dans les balises TextBlock. Les marges sont galement prsentes pour bien diffrencier les divers lments. Voyons maintenant le rsultat.
Si nous ajoutons un cadre, celui-ci prendra automatiquement toute la place restant disponible.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <DockPanel> <Border BorderThickness="1" BorderBrush="Black" Margin="2,2,2,2" HorizontalAlignment="Center">
Le guide du codeur 73
<TextBlock TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify"> <Bold>Grid</Bold>: Cette mthode est gnralement La mthode la plus recommande car elle offre un trs haut niveau dadaptabilit du contenu de lcran sa taille et donc galement aux changements de rsolution. Elle est toutefois plus complexe mettre en uvre. </TextBlock> </Border> </DockPanel> </Page>
Lordre des contrles a une importance capitale quant au rsultat obtenu. Si nous ajoutons un cinquime cadre et que nous xions lattribut DockPanel.Dock Bottom, le cadre noccupera pas lentiret du bas dcran comme cest le cas pour le cadre du haut.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <DockPanel> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Top" Margin="2,2,2,2" > <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black"
74 Le guide du codeur
Utiliser le docking
DockPanel.Dock="Right" Margin="2,2,2,2" Width="200"> <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Left" Width="200" Margin="2,2,2,2" HorizontalAlignment="Left"> <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Bottom" Margin="2,2,2,2" > <TextBlock TextWrapping="WrapWithOverflow" Margin="5,5,5,5" TextAlignment="Justify"> <Bold>WrapPanel</Bold> La mise en page avec un WrapPanel nest pas du tout adapte lexemple prcdent. En effet avec un WrapPanel les contrles sont placs cot les un des autres et sont renvoys automatiquement la ligne lorsque la fin de celle-ci est atteinte. </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" Margin="2,2,2,2" HorizontalAlignment="Center"> <TextBlock TextWrapping="WrapWithOverflow"
Le guide du codeur 75
En revanche, si dans le code nous dplaons ce dernier cadre avant les cadres de gauche et de droite, elle occupe alors toute la largeur.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <DockPanel> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Top" Margin="2,2,2,2" > <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Bottom" Margin="2,2,2,2" > <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Right" Margin="2,2,2,2" Width="200"> <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Left" Width="200" Margin="2,2,2,2" HorizontalAlignment="Left"> <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> <Border BorderThickness="1" BorderBrush="Black" Margin="2,2,2,2" HorizontalAlignment="Center"> <TextBlock TextWrapping="WrapWithOverflow" </TextBlock> </Border> </DockPanel> </Page>
76 Le guide du codeur
Autoriser le dlement
Suivant cette mme technique, vous pouvez ordonner les contrles pour obtenir la segmentation qui vous convient.
La balise ScrollViewer gre la fois la barre horizontale et verticale. Dans lexemple, les attributs ScrollViewer.HorizontalScrollBarVisibility et ScrollViewer.VerticalScrollBarVisibility sont initialiss Auto. Cela correspond lusage le plus frquent pour les barres de dlement. En mode automatique, les barres ne sont visibles que lorsquelles deviennent obligatoires. Les autres valeurs possibles sont Disabled, qui a pour effet de ne pas avoir de barre de dlement dans la direction correspondante ; Hidden, qui naffiche pas
78 Le guide du codeur
Autoriser le dlement
la barre de dlement, mais le contenu se comporte comme si celle-ci tait prsente, cest--dire quil ny aura pas de passage la ligne automatique ; la dernire valeur possible est Visible, qui fonctionne comme Auto la diffrence prs que la barre de dlement est visible mme si elle nest pas utile. Dans ce dernier cas, elle sera grise.
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible">
Valeur par dfaut Si vous ne spciez que la balise ScrollViewer, la barre horizontale sera cache et inactive (Hidden) alors que la barre verticale sera visible (Visible).
Lutilisation dun ScrollViewer ne se limite pas au bord de la fentre. Vous pouvez parfaitement en intgrer dautres dans linterface.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible"
Le guide du codeur 79
ScrollViewer.VerticalScrollBarVisibility="Hidden"> <StackPanel> <Border Width="200" Height="200" BorderBrush="Black" BorderThickness="1"> <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible"> <TextBox TextWrapping="Wrap" AcceptsReturn="True"> Cet exemple dmontre lutilisation dun ScrollView. </TextBox> </ScrollViewer> </Border> </StackPanel> </ScrollViewer> </Page>
Tapez du texte dans la bote de texte et vous verrez apparatre la barre de dlement.
80 Le guide du codeur
Nous commenons par dnir une barre de dlement horizontale et une verticale.
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible">
Le premier conteneur dni est un DockPanel. Il va nous permettre de dcouper la fentre en quatre zones. Une pour len-tte, une pour le bas de page et deux pour le corps de la fentre.
<DockPanel>
Le guide du codeur 81
Ensuite le bas dcran, qui de faon quil occupe toute la largeur de la fentre doit tre dni ce moment. Il contient galement un Canvas dans lequel le contrle est positionn depuis le coin infrieur droit.
<Canvas DockPanel.Dock="Bottom" Background="Green" MinHeight="30"> <Label Name="lblCopyright" Content="Le concepteur 2006" Canvas.Bottom="3" Canvas.Right="10" VerticalAlignment="Bottom" HorizontalAlignment="Right"/> </Canvas>
La partie droite du corps contient un WrapPanel. Cette partie sera xe lors dun redimensionnement horizontal.
<Border DockPanel.Dock="Right" MinWidth="200" MaxWidth="400" BorderThickness="1" BorderBrush="Black" Background="LightGreen"> <WrapPanel> <Image Width="190" Margin="2,2,2,2"> <Image.Source> C:\Documents and Settings\All Users\ Documents\Mes images\ chantillons dimages\Hiver.jpg </Image.Source> </Image> <TextBox TextWrapping="Wrap" Width="195" Margin="2,2,2,2" AcceptsReturn="True" /> <TextBox TextWrapping="Wrap" Margin="2,2,2,2" AcceptsReturn="True" /> </WrapPanel> </Border>
Le dernier volet est coll sur le bord gauche et contient une grille. La grille sert alors positionner les diffrentes zones de saisie.
82 Le guide du codeur
La grille contient 2 colonnes et 6 lignes. La largeur de premire colonne est xe et plus troite que la seconde, tandis que la hauteur de la troisime ligne est xe un minimum de 40 points pour que la ComboBox reste suffisamment visible.
<Grid.ColumnDefinitions> <ColumnDefinition Width="80" /> <ColumnDefinition MinWidth="200"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition MinHeight="40"/> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Label Name="lblLivre" Grid.Row="0" Grid.Column="0"> Livre </Label> <TextBox Name="txtLivre" Grid.Row="0" Grid.Column="1" MaxLength="30" Height="23" Text="TL" VerticalAlignment="Top" Margin="2,2,2,2"/> <Label Name="lblAuteur" Grid.Row="1" Grid.Column="0"> Auteur </Label> <TextBox Name="txtAuteur" Grid.Row="1" Grid.Column="1" MaxLength="30" CharacterCasing="Upper" Height="23" VerticalAlignment="Top" Margin="2,2,2,2"/> <Label Name="lblColl" Grid.Row="2" Grid.Column="0"> Collection </Label> <ComboBox Name="txtColl" Grid.Row="2" Grid.Column="1" IsEditable="True" VerticalAlignment="Top" Margin="2,2,2,2"> <ComboBoxItem> Fiction </ComboBoxItem> <ComboBoxItem>
Le guide du codeur 83
Horreur </ComboBoxItem> <ComboBoxItem IsSelected="True"> Policier </ComboBoxItem> <ComboBoxItem> Historique </ComboBoxItem> <ComboBoxItem> Amour </ComboBoxItem> </ComboBox> <Label Name="lblISBN" Grid.Row="3" Grid.Column="0"> Numro ISBN </Label> <TextBox Name="txtISBN" Grid.Row="3" Grid.Column="1" MaxLength="15" Height="23" VerticalAlignment="Top" Margin="2,2,2,2"/> <Label Name="lblGenre" Grid.Row="4" Grid.Column="0"> Genre </Label> <TextBox Name="txtGenre" Grid.Row="4" Grid.Column="1" MaxLength="50" Height="23" VerticalAlignment="Top" Margin="2,2,2,2"/> <Grid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Button Grid.Row="0" Grid.Column="0" Content="Prcdent" Width="80" Height="30" /> <Button Grid.Row="0" Grid.Column="1" Content="Suivant" Width="80" Height="30" /> </Grid> </Grid> </Border> </DockPanel> </ScrollViewer> </Page>
84 Le guide du codeur
Erreur dans le code Le contenu de la balise image est volontairement scind en 3 lignes pour une question de lisibilit de lexemple. Toutefois, si vous dsirez le reproduire, il sera ncessaire de regrouper le nom du chier sur une mme ligne.
Analysons cet exemple. La mise en page se fait au moyen dun DockPanel inclus dans un ScrollViewer. Ce DockPanel est compos de 4 zones. La premire zone est le titre "Ma bibliothque". Il sinscrit naturellement en haut dcran. Nous utilisons donc lattribut Top pour le docking. Un cadre vert clair entoure la zone de titre. Ce cadre est ralis avec la balise Border.
<Border BorderThickness="2" DockPanel.Dock="Top" BorderBrush="LightGreen"> <Canvas Background="DarkSeaGreen" MinHeight="40" > <Label FontSize="24" FontFamily="Engravers MT" Content="Ma bibliothque" /> </Canvas> </Border>
Comme vous le voyez, cest le nud Border qui est le parent de ce groupe. Cest donc lui qui doit tre positionn par rapport notre DockPanel. Les autres
Le guide du codeur 85
lments suivent invitablement le mouvement. Le contrle Border inclut un Canvas, ce qui va nous permettre de positionner notre titre sur la base de coordonnes. Grce lutilisation du Canvas, nous pourrions avoir dautres contrles dans la barre de titre Pour obtenir la couleur du fond de notre barre de titre, il nous a suffi dutiliser lattribut Background du Canvas. Pour viter un crasement exagr, la hauteur minimale du Canvas est xe 40. Pour obtenir le bas dcran, nous faisons de mme mais cette fois sans utiliser de bord. Cest donc directement le Canvas qui reoit lattribut DockPanel.Dock="Bottom".
<Canvas DockPanel.Dock="Bottom" Background="Green" MinHeight="30"> <Label Name="lblCopyright" Content="Le concepteur 2006" Canvas.Bottom="3" Canvas.Right="10" VerticalAlignment="Bottom" HorizontalAlignment="Right"/> </Canvas>
An quils prennent toute la largeur de la fentre, nous commenons par dnir len-tte et le bas de page. Les autres zones de notre DockPanel sont dnies aprs. La troisime zone dnie est la zone de droite.
<Border DockPanel.Dock="Right" MinWidth="200" MaxWidth="400" BorderThickness="1" BorderBrush="Black" Background="LightGreen"> <WrapPanel> <Image Width="190" Margin="2,2,2,2"> <Image.Source> C:\Documents and Settings\All Users\ Documents\Mes images\ chantillons dimages\Hiver.jpg </Image.Source> </Image> <TextBox TextWrapping="Wrap" Width="195" Margin="2,2,2,2" AcceptsReturn="True" /> <TextBox TextWrapping="Wrap" Margin="2,2,2,2" AcceptsReturn="True" /> </WrapPanel> </Border>
Dans cette zone, les contrles sont positionns au moyen dun WrapPanel.
86 Le guide du codeur
Il est galement inclus dans un Border, simplement an dobtenir un n cadre noir autour. La dernire zone, celle de gauche, est ralise grce un Grid dans lequel les diffrents contrles sont positionns dans les cellules formes par la grille. Le Grid est lui-mme inclus dans un Border pour dnir un n cadre noir. Le fond est galement dni dans la balise Border, mais nous aurions tout aussi bien pu le dnir dans la balise Grid.
<Border DockPanel.Dock="Left" MinWidth="280" MinHeight="200" BorderThickness="1" BorderBrush="Black" Background="LightGreen"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="80" /> <ColumnDefinition MinWidth="200"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition MinHeight="40"/> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> </Grid> </Border>
Si nous examinons le contenu de plus prs, nous remarquons la prsence dun Grid lintrieur de notre Grid.
<Grid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Button Grid.Row="0" Grid.Column="0" Content="Prcdent" Width="80" Height="30" /> <Button Grid.Row="0" Grid.Column="1 Content="Suivant" Width="80" Height="30" /> </Grid>
Pourquoi ce Grid ? Tout simplement parce que les boutons doivent tre centrs dans la grille et que les colonnes dnies dans notre premier Grid sont de largeur diffrente. Ce nouveau Grid inclut, grce lattribut Grid.ColumnSpan,
Le guide du codeur 87
les deux colonnes. Dans ce nouveau Grid, qui occupe en dnitive toute la ligne, deux colonnes, cette fois de largeur identique, sont rednies.
Effet du redimensionnement La rgle du DockPanel, qui dtermine que le dernier lment occupe lespace restant, aura pour consquence lorsque vous redimensionnez la fentre que seule la zone de gauche va sadapter dans les deux sens. La taille des autres parties reste xe dans une direction.
Cet exemple dmontre quel point il est possible dintgrer les diffrents composants les uns dans les autres mais galement que chaque choix, et ce y compris lordre de chaque balise, va avoir un impact sur le rsultat nal. Comme les zones sont dnies volontairement dans un ordre bien dtermin, les contrles qui y sont inclus vont galement tre ordonns en fonction. Cet tat de fait peut ventuellement tre prjudiciable la qualit de votre interface graphique. En effet, lordre dapparition des contrles va galement rgir le dplacement du curseur avec la touche [Tab]. La solution ce problme est simple et dj connue de ceux qui ont lhabitude du dveloppement traditionnel. XAML met notre disposition lattribut TabIndex, qui va simplement rednir lordre de parcours avec la touche [Tab].
88 Le guide du codeur
<Frame Source="Page2.xaml" BorderBrush="Black" BorderThickness="1" Width="200" Height="100"/> </WrapPanel> </StackPanel> </Window> Page1.xaml contient : <Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <Label> Frame 1 </Label> </StackPanel> </Page> Page2.xaml contient : <Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <Label> Frame 2 </Label> </StackPanel> </Page>
Le guide du codeur 89
Contenu dun frame Si vous pouvez utiliser des frames aussi bien au sein dune balise Window que dune balise Page, la page rfrence par la balise Frame ne pourra en aucun cas tre une page utilisant la balise Window.
3.9 Checklist
Dans ce chapitre, nous avons essentiellement vu comment disposer les lments lcran et principalement :
j j j
j j j j
le positionnement par utilisation des coordonnes en utilisant Canvas ; le positionnement en utilisant une grille avec la classe Grid ; le positionnement en utilisant les panneaux de type StackPanel, WrapPanel et DockPanel ; le mlange de ces diffrentes mthodes ; autoriser le dlement avec ScrollViewer ; raliser des pages composes de plusieurs pages avec Frame ; comprendre et utiliser les attributs attachs.
90 Le guide du codeur
Ch apit re
Outre les attributs que nous avons dj voqus comme MaxWidth, repris dans lexemple, deux attributs sont particulirement intressants pour ce contrle. Il sagit tout dabord de SelectedIndex, qui permet de dnir une valeur par dfaut.
<ListBox Name="lstLangue" SelectedIndex="3" MaxWidth="80"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem>Italien</ListBoxItem> <ListBoxItem>Espagnol</ListBoxItem> </ListBox>
92 Le guide du codeur
Comme vous pouvez le constater en comparant le rsultat avec lcran ci-dessous, la prslection ne saffiche pas de la mme manire quun lment slectionn par lutilisateur.
Particularit de la numrotation Les diffrentes lignes de la liste de choix sont numrotes non pas de 1 n mais bien de 0 n-1 ; n tant le nombre dlments de la liste. Pour slectionner le premier, vous devez donc mettre comme valeur 0. Dans lexemple, la valeur slectionne est bien la quatrime, SelectedIndex vaut 3.
Le guide du codeur 93
Il existe une autre faon pour indiquer quel lment doit tre prslectionn. Cette mthode a lavantage dtre beaucoup plus visuelle car il sagit de modier dans la balise de llment voulu lattribut IsSelected. Le rsultat obtenu est le mme quavec lattribut SelectedIndex.
<ListBox Name="lstLangue" MaxWidth="80"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem IsSelected="true">Italien</ListBoxItem> <ListBoxItem>Espagnol</ListBoxItem> </ListBox>
Le second attribut intressant est lattribut SelectionMode, qui permet dautoriser ou dinterdire la slection de plusieurs valeurs. Si vous optez pour plusieurs valeurs, il existe deux modes possibles, en assignant soit la valeur Multiple, ce qui permet de slectionner ou de dslectionner plusieurs valeurs en cliquant simplement avec la souris, soit la valeur Extend, ce qui permet dutiliser les touches [Ctrl] et [Maj] pour raliser votre slection. La touche [Ctrl] permet dajouter votre slection llment sur lequel vous cliquez sans dslectionner les lments dj choisis. La touche [Maj] permet quant elle de slectionner tous les lments repris entre le dernier lment slectionn et llment sur lequel vous cliquez.
<ListBox Name="lstLangue" SelectionMode="Multiple" MaxWidth="80"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem>Italien</ListBoxItem> <ListBoxItem>Espagnol</ListBoxItem> </ListBox>
94 Le guide du codeur
Si vous dsirez raliser une prslection de plusieurs valeurs, il suffit de modier lattribut IsSelected de chaque lment prslectionner.
<ListBox Name="lstLangue" MaxWidth="80" SelectionMode="Multiple"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem IsSelected="true">Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem IsSelected="true">Italien</ListBoxItem> <ListBoxItem>Espagnol</ListBoxItem> </ListBox>
Prslectionner un lment avec SelectedValue Au lieu dutiliser SelectedIndex, vous pourriez utiliser lattribut SelectedValue. Toutefois, dans le code XAML, cela me semble peu opportun et plus compliqu. Il nen va pas ncessairement de mme si vous initialisez la valeur depuis le code .NET.
Si vous dsirez rendre une liste inaccessible lutilisateur, vous devrez utiliser lattribut IsEnabled. Ce contrle ne supporte pas lattribut IsReadOnly.
<ListBox Name="lstLangue" IsEnabled="False" MaxWidth="80"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem IsSelected="true">Italien</ListBoxItem> <ListBoxItem>Espagnol</ListBoxItem> </ListBox>
Le guide du codeur 95
Problme de lisibilit Cette faon de procder ne convient pas bien car, comme vous pouvez le constater, bien quune valeur soit prslectionne, elle nest pas visible. Pour rsoudre ce problme, assignez la valeur Blue lattribut Background de la balise ListBoxItem correspondante.
<ListBox Name="lstLangue" MaxWidth="80"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem Background="Blue" IsSelected="true"> Italien </ListBoxItem> <ListBoxItem>Espagnol</ListBoxItem> </ListBox>
Limite de cette modication Cette solution nest envisageable que si le contrle reste toujours ltat inactif. Dans le cas contraire, llment modi avec Background apparatra toujours comme slectionn.
96 Le guide du codeur
Si vous souhaitez que le contrle soit actif mais que certaines valeurs soient dsactives, il suffit de placer lattribut IsEnabled dans ltat False pour chacun des lments.
<ListBox Name="lstLangue" MaxWidth="80"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem IsEnabled="False">Italien</ListBoxItem> <ListBoxItem IsEnabled="False">Espagnol</ListBoxItem> </ListBox>
b Figure 4-7 : Une liste de choix dont certains lments sont dsactivs
Si la hauteur de la liste nest pas suffisante, une barre de dlement sera automatiquement ajoute.
<ListBox Name="lstLangue" MaxWidth="80" MaxHeight="45"> <ListBoxItem>Franais</ListBoxItem> <ListBoxItem>Anglais</ListBoxItem> <ListBoxItem>Allemand</ListBoxItem> <ListBoxItem IsEnabled="False">Italien</ListBoxItem> <ListBoxItem IsEnabled="False">Espagnol</ListBoxItem> </ListBox>
Le guide du codeur 97
98 Le guide du codeur
Lattribut IsEditable permet de dnir si oui ou non vous pouvez encoder une valeur diffrente dune des valeurs de la liste.
<ComboBox Name="cboPays" SelectedIndex="4" IsEditable="True" Height="20" Margin="2,2,2,2"> <ComboBoxItem>France</ComboBoxItem> <ComboBoxItem>Belgique</ComboBoxItem> <ComboBoxItem>Allemagne</ComboBoxItem> <ComboBoxItem>Suisse</ComboBoxItem> <ComboBoxItem>Italie</ComboBoxItem> <ComboBoxItem>Espagne</ComboBoxItem> </ComboBox>
Le fait que ce contrle soit ditable a pour consquence quil possde la fois des attributs de ListBox et de TextBox. Cest pourquoi vous pouvez par exemple assigner lattribut Text, qui aura pour effet de placer cette valeur dans la zone de saisie.
Lattribut IsReadOnly Lattribut IsReadOnly provoque un comportement inattendu. En effet, le fait de placer le contrle en lecture seule au moyen de cet attribut nempche pas lutilisateur de choisir dans la liste et ainsi de changer la valeur. Cet attribut naffecte que la zone de saisie du texte. Si vous dsirez que la valeur ne puisse tre change, il est ncessaire dassigner la valeur False lattribut IsEnabled.
Le guide du codeur 99
Si pour une raison particulire vous dsirez retirer la possibilit de rechercher dans la liste en tapant successivement les lettres du dbut du mot recherch, lattribut IsTextSearchEnabled doit tre mis False.
<ComboBox Name="cboPays" SelectedIndex="4" IsTextSearchEnabled="False" Height="20" Margin="2,2,2,2"> <ComboBoxItem>France</ComboBoxItem> <ComboBoxItem>Belgique</ComboBoxItem> <ComboBoxItem>Allemagne</ComboBoxItem> <ComboBoxItem>Suisse</ComboBoxItem> <ComboBoxItem>Italie</ComboBoxItem> <ComboBoxItem>Espagne</ComboBoxItem> </ComboBox>
Lattribut IsChecked reoit une valeur boolenne qui indique si par dfaut la case est coche ou non. Si vous ne souhaitez pas que la case soit coche par dfaut, vous pouvez bien sr omettre tout simplement cet attribut. Parfois, vous aurez besoin dune case cocher autorisant ltat indtermin. Cest lattribut IsThreeState qui va autoriser ce comportement.
<CheckBox Name="chkDispo" Margin="5,5,2,2" IsThreeState="True" > Disponible en semaine </CheckBox>
Si vous souhaitez utiliser ce contrle uniquement pour afficher une information mais que vous ne souhaitiez pas que lutilisateur puisse modier ltat de la case cocher, vous devez ici encore utiliser obligatoirement lattribut IsEnabled.
<CheckBox Name="chkDispo" Margin="5,5,2,2" IsEnabled="False" IsChecked="True" Content="Disponible en semaine" />
Lattribut Content Dans ce dernier exemple, le texte est assign lattribut Content au lieu de le placer dans le nud. Le rsultat est identique, cest une question de got personnel.
Comme pour la case cocher, nous retrouvons lattribut IsChecked. la diffrence de la case cocher, les boutons radio sont associs les uns aux autres. Ce qui fait que, quand vous slectionnez un bouton radio, les autres sont automatiquement dslectionns.
<RadioButton Name="rbUseVB" IsChecked="True"> Jutilise VB.NET </RadioButton> <RadioButton Name="rbUseCSharp">
102 Le guide du codeur
Si vous dsirez avoir dans un mme cran plusieurs listes de boutons radio indpendantes les unes des autres, vous devez les intgrer dans un ensemble. Dans les versions prcdentes, nous aurions d utiliser une RadioButtonList mais elle nest actuellement plus disponible en XAML. Pour regrouper des boutons radio dans des ensembles diffrents, le moyen le plus simple est de leur ajouter un attribut GroupName. Assignez la mme valeur cet attribut pour tous les boutons radio devant tre associs.
<RadioButton Name="rbUseVB" IsChecked="True" GroupName="grpLanguage"> Jutilise VB.NET </RadioButton> <RadioButton Name="rbUseCSharp" GroupName="grpLanguage"> Jutilise C# </RadioButton> <RadioButton Name="rbUsedelphi" GroupName="grpLanguage"> Jutilise Delphi.NET </RadioButton> <RadioButton Name="rbUse10" GroupName="grpFramework"> Jutilise le Framework 1.0 </RadioButton> <RadioButton Name="rbUse11" IsChecked="True"
GroupName="grpFramework"> Jutilise le Framework 1.1 </RadioButton> <RadioButton Name="rbUse20" GroupName="grpFramework"> Jutilise le Framework 2.0 </RadioButton>
Une autre solution consiste utiliser un contrle conteneur spar pour chaque liste de boutons radio. Dans lexemple ci-dessous, nous utiliserons deux StackPanel supplmentaires. Cest pourquoi, pour cet exemple, le code complet vous est nouveau prsent.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <StackPanel> <RadioButton Name="rbUseVB" IsChecked="True"> Jutilise VB.NET </RadioButton> <RadioButton Name="rbUseCSharp"> Jutilise C# </RadioButton> <RadioButton Name="rbUsedelphi"> Jutilise Delphi.NET </RadioButton> </StackPanel> <StackPanel>
<RadioButton Name="rbUse10"> Jutilise le Framework 1.0 </RadioButton> <RadioButton Name="rbUse11" IsChecked="True"> Jutilise le Framework 1.1 </RadioButton> <RadioButton Name="rbUse20"> Jutilise le Framework 2.0 </RadioButton> </StackPanel> </StackPanel> </Page>
Le rsultat est identique la mthode prcdente. Toutefois, lutilisation dune mthode ou dune autre peut inuencer la mise en page.
Liste de choix non modiable Pour rendre une liste de choix non modiable, vous devez utiliser lattribut IsEnabled. Celui-ci doit tre appliqu sur chaque bouton radio. Toutefois, si elle est incluse dans un conteneur qui lui est spcique, vous pouvez spcier lattribut IsEnabled dans le conteneur. Cette faon de faire est bien plus pratique bien des gards.
Normalement, il devrait tre possible dutiliser un contrle de type GroupBox au lieu dun Canvas. Toutefois, dans la version bta utilise au moment dcrire ces lignes, cette possibilit ntait pas supporte. Le contrle GroupBox existe bel et bien mais ne supporte quun enfant et ne permet ds lors pas de regrouper les boutons radio. Son utilisation se limite laffichage du traditionnel contour. Son utilit reste malgr tout vidente pour rendre votre interface claire et bien comprhensible pour lutilisateur.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <StackPanel> <GroupBox BorderThickness="1" BorderBrush="Black" Header="Language" Width="150"> <StackPanel> <RadioButton Name="rbUseVB" IsChecked="True"> Jutilise VB.NET </RadioButton> <RadioButton Name="rbUseCSharp"> Jutilise C# </RadioButton>
Le guide du codeur 105
<RadioButton Name="rbUsedelphi"> Jutilise Delphi.NET </RadioButton> </StackPanel> </GroupBox> <GroupBox BorderThickness="1" BorderBrush="Black" Header="Framework" Width="150"> <StackPanel> <RadioButton Name="rbUse10"> Jutilise le Framework 1.0 </RadioButton> <RadioButton Name="rbUse11" IsChecked="True"> Jutilise le Framework 1.1 </RadioButton> <RadioButton Name="rbUse20"> Jutilise le Framework 2.0 </RadioButton> </StackPanel> </GroupBox> </StackPanel> </Page>
Notez au passage lutilisation de lattribut Header pour indiquer le titre de votre GroupBox.
en dehors des programmes commerciaux. Pourtant, elles apportent un rel plus votre dveloppement et, surtout, elles vitent pas mal dincomprhension et de confusion pour lutilisateur de votre interface. Pour des questions de place lcran, les tiquettes prcdant les diffrents champs de saisie ou de choix sont gnralement fortement rsumes et trs peu explicites. Les bulles dinformation sont l pour pallier ce manque et constituent le premier niveau daide. Pour raliser une telle bulle, vous devez utiliser lattribut ToolTip du contrle auquel la bulle dinformation doit tre associe. titre dexemple, nous allons associer une bulle dinformation une bote de saisie de texte.
<TextBox Name="txtNom" Margin="3,3,3,3" ToolTip="Dans ce champ vous devez introduire le nom de famille de votre contact." />
Cette faon de faire est toutefois limite la prsentation sur une seule ligne. Pour amliorer notre info-bulle, nous devons utiliser une syntaxe lgrement plus complique en la dnissant comme un nud ls.
<TextBox Name="txtNom" Margin="3,3,3,3"> <TextBox.ToolTip> <TextBlock MaxWidth="200" TextWrapping="WrapWithOverflow" > Dans ce champ vous devez introduire le nom de famille de votre contact. </TextBlock> </TextBox.ToolTip> </TextBox>
De cette faon, le texte dinformation est alors inclus dans un bloc de texte, ce qui permet dajuster les attributs daffichage pour obtenir le rsultat souhait. Dans lexemple, la taille de la bulle est limite 150 pixels et le texte passe automatiquement la ligne en tendant la zone autant que ncessaire.
Outre le passage la ligne, cette faon daborder le problme offre galement la possibilit denrichir la prsentation du contenu.
<TextBox Name="txtNom" Margin="3,3,3,3"> <TextBox.ToolTip> <TextBlock MaxWidth="200" TextWrapping="WrapWithOverflow" > <Image Width="16" Height="16"> <Image.Source> C:\Windows\Microsoft.NET\Windows\ v6.0.5070\Avalon\avalonArp.ico </Image.Source> </Image> Dans ce champ vous devez introduire le <Bold>nom</Bold> de <Underline>famille </Underline> de votre contact. </TextBlock> </TextBox.ToolTip> </TextBox>
Bien quil reprsente une surface, le TabControl est plus proche des contrles de type TextBox que du Canvas, par exemple. En effet, chaque nud TabItem ne peut avoir quun seul enfant. Pour pallier ce problme, la solution est trs simple et revient
Renvoi appliquer les rgles qui sont vues dans le chapitre Mlanger les
<Image Grid.Column="0" Grid.Row="0" Source="C:\Documents and Settings\All Users\ Documents\Mes images\chantillons dimages\ Collines.jpg" /> <Image Grid.Column="0" Grid.Row="1" Source="C:\Documents and Settings\All Users\ Documents\Mes images\chantillons dimages\ Coucher de soleil.jpg" /> <Image Grid.Column="1" Grid.Row="0" Source="C:\Documents and Settings\All Users\ Documents\Mes images\chantillons dimages\ Hiver.jpg" /> <Image Grid.Column="1" Grid.Row="1" Source="C:\Documents and Settings\All Users\ Documents\Mes images\chantillons dimages\ Nnuphars.jpg" /> </Grid> </TabItem>
Utilisation de IsSelected Remarquez au passage lutilisation de IsSelected pour spcier un onglet par dfaut diffrent du premier.
Pour obtenir un contrle efficace du comportement de ce bouton rptition, nous disposons tout dabord de lattribut Interval, qui dtermine le temps entre deux appels de laction associe au bouton.
<RepeatButton Name="btnSuivant" Width="80" Height="30" Interval="100"> Suivant </RepeatButton>
Dans lexemple, lopration Suivant sera effectue tous les diximes de seconde. Pour viter que la rptition ne dmarre directement, vous pouvez imposer un dlai. Si la pression sur le bouton est infrieure au dlai, il se comportera comme un bouton normal. En revanche, si la pression se prolonge au-del du dlai x, la rptition de tche va pouvoir dmarrer. Pour contrler ce dlai, vous disposez de lattribut Delay.
<RepeatButton Name="btnSuivant" Delay="500" Interval="100"> Suivant </RepeatButton>
Dure du traitement La dure du traitement raliser chaque rptition ne peut excder lintervalle prvu entre chaque rptition. Dans le cas contraire, le traitement pourrait se poursuivre encore un certain temps aprs que lutilisateur eut relch le bouton.
Comme vous pouvez le constater, visuellement, il ny a aucune diffrence entre les deux types de boutons. Si vous dsirez visuellement identier ce type de bouton, vous pouvez adapter pour lui votre charte graphique en changeant par exemple la couleur du fond. Pour rappel, vous disposez pour cela de lattribut Background. Vous pouvez galement jouer sur leffet visuel li la forme du curseur de la souris.
<RepeatButton Name="btnSuivant" Delay="500" Interval="100" Cursor="Hand"> Suivant </RepeatButton>
Dans lexemple ci-dessus, le curseur de la souris est transform en une main lors du passage sur le bouton.
Gnralement, ce genre de contrle dispose de repres visuels. Il existe deux possibilits pour les ajouter, en utilisant soit lattribut TickFrequency, qui vous permet de dnir lcart entre chaque repre :
<Slider Width="200" VerticalAlignment="Center" Minimum="0" Maximum="100" Value="50" TickFrequency="10" TickPlacement="BottomRight"/>
Utiliser un Slider
Ce dernier est plus contraignant mais permet davoir des repres qui sont irrguliers. En plus des repres visuels, vous pouvez ajouter automatiquement la valeur dans un ToolTip.
<Slider Width="200" VerticalAlignment="Center" Minimum="0" Maximum="100" Value="50" Ticks="10,20,30,40,50,60,70,80,90" TickPlacement="BottomRight" AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="0" />
Limiter les valeurs aux repres Avec lattribut IsSnapToTickEnabled, les valeurs sont automatiquement arrondies au repre le plus proche.
Il est galement possible de modier la valeur sans dplacer le curseur mais en cliquant sur la barre. LargeChange permet de dnir la valeur qui sera ajoute ou retire automatiquement chaque clic. Les attributs Delay et Interval permettent de moduler automatiquement la rptition de laction.
<Slider Width="200" VerticalAlignment="Center" Minimum="0" Maximum="100" Value="50" Ticks="10,20,30,40,50,60,70,80,90" TickPlacement="BottomRight" AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="0" LargeChange="10" Delay="500" Interval="200" />
Vous pouvez galement dnir une zone visuelle o devrait se trouver la valeur. Cette zone est un attribut purement visuel mais ne limite en rien les valeurs possibles.
<Slider Width="200" VerticalAlignment="Center" Minimum="0" Maximum="100" Value="50" Ticks="10,20,30,40,50,60,70,80,90" TickPlacement="BottomRight" AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="0" LargeChange="10" Delay="500" Interval="200" IsSelectionRangeEnabled="True" SelectionStart="20" SelectionEnd="80" />
Si vous prfrez un Slider vertical, aucun problme, la proprit Orientation vous permet de choisir entre horizontal (par dfaut) ou vertical.
<Slider HorizontalAlignment="Center" Minimum="0" Maximum="100" Value="50" Ticks="10,20,30,40,50,60,70,80,90" TickPlacement="BottomRight" AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="0"
116 Le guide du codeur
Utiliser un Slider
Dnition de la taille En orientation verticale, la taille est contrle non plus par lattribut Width mais bien par lattribut Height.
Une autre solution est dutiliser un Expander. Celui-ci a la facult dafficher ou de cacher son contenu en ne laissant alors visible que son titre.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Expander" > <StackPanel> <Expander Header="Informations" IsExpanded="false"> <TextBlock> Cette zone contient un texte dinformation </TextBlock> </Expander>
Utiliser un Expander
Un Expander peut parfaitement contenir plus dun contrle utilisateur mais, dans ce cas, ils devront tre encapsuls dans un conteneur.
<Expander Header="Contenu" IsExpanded="true"> <StackPanel> <WrapPanel> <Label Width="60"> Nom: </Label> <TextBox Name="txtNom" Width="150"/> </WrapPanel> <WrapPanel> <Label Width="60"> Prnom: </Label> <TextBox Name="txtprenom" Width="150"/> </WrapPanel> </StackPanel> </Expander> <Expander Header="Plus"> <WrapPanel> <Label Width="60"> Tl: </Label> <TextBox Name="txttel" Width="150"/> </WrapPanel> </Expander> <Button Width="80"> Ok </Button> </StackPanel> </Page>
Pour ouvrir ou fermer un Expander, il suffit dutiliser les ches sur sa droite ; lorientation des ches indique sil est ouvert ou ferm. Si les ches sont diriges vers le bas, le contenu est cach. A contrario, si les ches sont diriges vers le haut, le contenu est affich.
Comme vous pouvez le constater, il est possible de mettre plusieurs Expander dans une mme page. En revanche, un Expander ne peut avoir quun seul nud enfant. Celui-ci sera ds lors souvent un conteneur comme un StackPanel. Notez dans lexemple lutilisation combine de StackPanel et de WrapPanel. Lattribut Header permet de dterminer le titre, alors que lattribut IsExpanded indique si la zone est cache (false) ou affiche (true). Par dfaut, le contenu est cach. Notez que le bouton ne sera jamais cach car il nest pas repris dans une balise
Expander.
Direction dexpansion Si vous souhaitez que la zone souvre vers le haut plutt que vers le bas, utilisez lattribut ExpandDirection et assignez-lui la valeur Up.
Grce loption Stretch="Fill", le contenu occupe automatiquement lentiret de la ViewBox. Lattribut StretchDirection vous permet de limiter lagrandissement au sens horizontal ou vertical. Si vous changez la largeur de 150 en 50, le contenu est modi en fonction.
Selon la valeur donne lattribut Stretch, le rsultat sera fort diffrent. Pour bien comprendre le fonctionnement de chacune de ces valeurs, voici un autre exemple.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <WrapPanel> <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5"> <Viewbox Width="70" Height="100" Stretch="None" StretchDirection="Both"> <Image Source="c:\Mir.bmp" Width="50" Height="50"/> </Viewbox> </Border> <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5"> <Viewbox Width="70" Height="100" Stretch="Fill" StretchDirection="Both"> <Image Source="c:\Mir.bmp" Width="50" Height="50"/> </Viewbox> </Border> <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5"> <Viewbox Width="70" Height="100" Stretch="Uniform" StretchDirection="Both">
Utiliser un Popup
<Image Source="c:\Mir.bmp" Width="50" Height="50"/> </Viewbox> </Border> <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5"> <Viewbox Width="70" Height="100" Stretch="UniformToFill" StretchDirection="Both"> <Image Source="c:\Mir.bmp" Width="50" Height="50"/> </Viewbox> </Border> </WrapPanel> </Page>
Pour une question de clart de lexemple, la taille de limage est xe dans le code 50 sur 50 et est place dans quatre ViewBox identiques lexception de la valeur de lattribut Stretch. Les balises Border sont uniquement prsentes pour dlimiter visuellement lemplacement des ViewBox. Le rsultat parle de lui-mme.
AffichePopup est excute et que, lorsque vous cliquez sur le bouton Cliquer pour fermer, cest la mthode CachePopup qui est excute.
<Page x:Class="Page1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <Button Name="MonBouton" Click="AffichePopup"> Cliquez pour ouvrir </Button> <Popup Name="MonPopup" PlacementTarget="{Binding ElementName=MonBouton}" PlacementRectangle="30,20,100,40"> <Border BorderThickness="1" BorderBrush="Black"> <StackPanel Margin="5,5,5,5" Background="AliceBlue"> <Label> Ceci nest pas un tooltip mais un popup et peut tre une page part entire </Label> <Button Click="CachePopup"> Cliquez pour fermer </Button> </StackPanel> </Border> </Popup> </StackPanel> </Page> Interaction logic for Page1.xaml Partial Public Class Page1 Inherits Page Public Sub New() InitializeComponent() End Sub Public Sub AffichePopup(ByVal sender As Object, ByVal e As RoutedEventArgs) Me.MonPopup.IsOpen = True End Sub
Utiliser un Popup
Public Sub CachePopup(ByVal sender As Object, ByVal e As RoutedEventArgs) Me.MonPopup.IsOpen = False End Sub End Class
Comme vous pouvez le constater, rien ne suggre quil puisse y avoir un Popup.
MediaElement est simplement place dans un cadre. La proprit Source permet de dnir le chier multimdia qui devra tre utilis. La proprit LoadedBehavior permet de dterminer laction qui sera prise directement aprs le chargement du contrle. La proprit UnloadedBehavior a le mme effet mais lors du dchargement du contrle. Les valeurs possibles sont Stop, Play, Close, Pause, NoSet et Manual.
cran vide Il est possible que lemplacement o devrait se trouver la vido reste vide. Il sagit dun problme de pilote de la carte cran qui nest pas adapt. En effet, MediaElement requiert un pilote rcent et adapt. Si cest votre cas, essayez de mettre jour votre pilote. Cest aussi pour cette raison que lcran vous est prsent sous Windows Vista et non sous Windows XP comme les autres crans.
Il existe galement une classe SoundPlayer et une MediaPlayer. SoundPlayer ne peut tre utilise directement en XAML mais uniquement en code .NET. De manire gnrale, lutilisation de MediaElement est trs largement privilgie, et tout particulirement dans le code XAML. Il est possible galement dutiliser les Triggers pour manipuler la vido depuis, par exemple, des boutons. Dans lexemple qui suit, un bouton Play permet de dmarrer la vido et un bouton Pause permet de larrter. Si vous voulez plus dinformations sur les triggers, reportez-vous au
Renvoi chapitre Utiliser les Triggers page 238.
<Window x:Class="Window1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WindowsApplication8" Height="300" Width="300" > <Window.Triggers>
Le storyboard a dni une MediaTimeLine qui est une TimeLine spcique aux lments multimdias. Cest ici quest dnie la source.
<MediaTimeline Source="c:\news.wmv" Storyboard.TargetName="laVideo"/> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger>
Checklist
Mthodes de MediaElement Vous pouvez remarquer qu aucun moment nous navons utilis les mthodes Start et Pause de la classe MediaElement.
4.13 Checklist
Ce chapitre a t loccasion de passer en revue les diffrents contrles permettant de raliser une interface utilisateur complte. Cest--dire :
j
crer et manipuler les listes droulantes, que ce soient les ListBox ou les
ComboBox ;
j j j j j j j j j j
utiliser les cases cocher (CheckBox) ; utiliser les boutons radio (RadioButton) et les grouper ; crer des info-bulles (ToolTip) ; crer un panneau onglets (TabControl) ; congurer un bouton pour le rendre autorptitif ; utiliser un curseur (Slider) pour dterminer une valeur ; utiliser des Expander pour rendre linterface plus lisible ; utiliser une ViewBox ; crer des fentres Popup ; manipuler le multimdia avec MediaElement.
Ch apit re
Ce type nest pas prsent Si vous ne trouvez pas ce type de projet dans Visual Studio, cest que vous navez pas install le kit de dveloppement ou, selon les versions, ladd-in pour Visual Studio. Vous le trouverez sur le site de Microsoft.
Au lieu du traditionnel Form1.vb, vous retrouvez quatre chiers diffrents. Ils sont associs par paire : les chiers MyApp.xaml et MyApp.xaml.vb, dune part, et les chiers Window1.xaml et Window1.xaml.vb, dautre part. Chaque paire de chiers prend en charge la gestion dune classe. Il est vrai que, si vous avez dj travaill avec Visual Studio 2005, vous savez que derrire le chier Form1.vb se cachait un chier Form1.Designer.vb. Le but dans les deux cas est le mme : sparer le code daffichage du code de traitement. Mais revenons notre projet et examinons pour commencer le chier MyApp.xaml. <Application x:Class="MyApp" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="Window1.xaml"> <Application.Resources> </Application.Resources> </Application> A priori, il est probable que vous nayez pas changer ce chier sauf lattribut
StartupUri, qui dnit la classe instancier et excuter au dmarrage de lapplication. Il ne serait pas de bon ton de conserver pour votre classe le nom par dfaut. Remplacez Window1.xaml par HelloWorld.xaml.
Comme vous le voyez, ce niveau rien dire. Dans la majorit des cas, vous naurez pas ajouter du code dans cette partie. Nhsitez pas, toutefois,
changer le nom MyApp en un nom plus cohrent. Faites-le galement dans le chier xaml et renommez aussi les chiers.
Proprits de lapplication Quand vous changez le nom du chier MyApp, la proprit Action de gnration du chier devient Page. Vous devez remettre la valeur ApplicationDefinition. Pour y accder, cliquez du bouton droit sur le nom du chier et choisissez Proprits.
Nom des classes Si le nom des classes diffre entre le chier XAML et le chier xaml.vb, vous aurez immanquablement une erreur la compilation. Les chiers peuvent porter un autre nom que la classe mais il est de bon aloi de garder le mme.
<Window x:Class="HelloWorld" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Ma premire application" > <Grid> </Grid> </Window>
Comme vous pouvez le constater, Microsoft vous propose par dfaut lutilisation dune grille. Contrairement aux exemples vus jusqu prsent, la premire balise est une balise Window et non plus une balise Page. La balise Window est utilise pour dnir une fentre de type Windows. Nous reviendrons ultrieurement sur lutilisation de la balise Page. Ajoutons le code suivant entre les balises Grid.
<Label VerticalAlignment="Center" HorizontalAlignment="Center"> Bonjour le monde. </Label>
La balise Window dispose comme les autres balises dun grand nombre dattributs. Certains comme Width ou MinHeight ont dj t vus dans dautres chapitres et nous ne reviendrons pas dessus. En revanche, il existe quelques autres attributs fort intressants. Vous avez dj pu voir dans les exemples laction de lattribut Title, qui permet de dnir le titre de la fentre. Pour positionner la fentre, vous disposez de lattribut WindowsStartupLocation, qui va dterminer la position initiale de la fentre.
WindowStartupLocation="CenterScreen"
Les valeurs possibles sont CenterScreen pour centrer la fentre dans lcran, idal pour la fentre principale ; CenterOwner pour centrer la fentre dans la fentre qui la contient, idal pour les sous-fentres ; et Manual pour vous permettre de choisir la position vous-mme. Cette dernire valeur est utiliser en conjonction avec les attributs Top et Left.
<Window x:Class="HelloWorld" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Ma premire application" WindowStartupLocation="Manual" Top="100" Left="300" >
Un autre attribut intressant est lattribut SizeToContent. Sil est x True, la taille de la fentre lors de la cration sera automatiquement adapte au contenu.
SizeToContent="WidthAndHeight"
Il est possible de nadapter la taille quen largeur en utilisant la valeur Width ou uniquement en hauteur en utilisant la valeur Height. Vous pouvez galement opter pour dmarrer automatiquement en mode maximis ou minimis.
WindowState="Maximized"
Il est galement possible de modier le comportement et les possibilits de redimensionnement des fentres en utilisant lattribut ResizeMode.
ResizeMode="CanResizeWithGrip"
Notez le grip en bas droite. Vous pouvez galement opter pour interdire le redimensionnement avec la valeur NoResize. La taille de la fentre nest pas la seule chose que nous puissions modier, il est galement possible de modier son affichage en ajoutant lattribut WindowStyle. Par dfaut, sa valeur est SingleBorderWindow, mais vous pouvez ajouter un effet 3D.
WindowStyle="ThreeDBorderWindow"
Pour certaines fentres, vous souhaiterez peut-tre quil ne soit pas possible de les recouvrir avec une autre. Si cest le cas, utilisez lattribut Topmost.
Topmost="True"
Par dfaut, toutes les fentres sont automatiquement reprises dans la barre des tches. Si, pour la fentre principale, cette option par dfaut est judicieuse, ce nest pas toujours le cas pour les autres fentres. Pour viter quune fentre ne soit reprise dans la barre des tches, il suffit dutiliser lattribut ShowInTaskbar.
ShowInTaskbar="False"
Centrage Les attributs ralisant le centrage sont dplacs du Label au StackPanel. Sans cela, vu le type de fonctionnement du StackPanel, le centrage vertical dans la fentre naurait pas lieu.
Un bouton a galement t ajout la fentre. La question est maintenant de savoir comment associer une action au bouton. Comme vous pouvez limaginer, laction sera ralise dans le code .NET au sein dune mthode de la classe. Ceci tant entendu, le problme se rsume alors associer le bouton la mthode voulue. Tout dabord, il faut savoir que la mthode doit tre associe non pas au bouton lui-mme mais un vnement du bouton. En loccurrence, lvnement Click. Commenons par crire dans le code VB une mthode que vous dsirez excuter.
Public Sub Click_Repondre(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.lblTexte.Content = "Merci" Me.btnRepondre.IsEnabled = False End Sub
Cette mthode va remplacer le texte "Bonjour le monde" par "Merci". La signature de la mthode, cest--dire les diffrents paramtres, doit absolument respecter la dnition reprise dans lexemple. Elle correspond par ailleurs strictement la dnition des mthodes charges de rpondre aux vnements dans lenvironnement .NET. Le nom est quant lui entirement libre, mais choisissez toujours un nom parlant.
Utiliser lIntelliSense Pour bncier de lIntelliSense et ainsi retrouver facilement les noms des membres que vous aurez dnis dans votre code XAML, nhsitez pas utiliser le mot cl ME mme sil est facultatif.
Maintenant que nous avons dni la mthode, il ne reste plus quune simple tape faire, raliser lassociation entre lvnement et la mthode. Nous pourrions classiquement le faire en .NET mais il est plus judicieux de le faire dans le code XAML.
<Button Name="btnSuite" Click="Click_Repondre"> Suite </Button>
Cest aussi simple que cela. Le nom de lattribut correspond au nom de lvnement et la valeur est le nom de la mthode appeler.
La mme technique peut tre applique avec nimporte quel vnement de nimporte quelle classe.
tirer parti de toute la puissance des API WinFX ou presque, et ce y compris les fonctionnalits 3D. Toutefois, comme pour lASP.NET, le dveloppement se fait en mode Page. Contrairement une application ASP.NET, les pages sont codes dans un mme module. Leur accs se fera alors sans devoir faire appel au serveur. En revanche, le fait que lapplication soit excute sur le poste client rend ncessaire la prsence de WinFX sur le poste client. Il ne sagit donc pas dune technologie universelle indpendante de la plate-forme utilise comme lest le HTML.
Le contenu du projet est trs semblable au contenu pour une application Windows.
Vous y retrouvez les deux paires de chiers mais, cette fois, au lieu de Window1 les chiers se nomment Page1. Voyons le contenu de ces quatre chiers et les diffrences par rapport ceux raliss dans lapplication Windows (voir p. 132). Si ce nest ladresse de lURI, les chiers MyApp.xaml et MyApp.xaml.vb sont identiques ceux dj vus.
<Application x:Class="MyApp" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="Page1.xaml" > <Application.Resources> </Application.Resources> </Application> Interaction logic for MyApp.xaml Partial Public Class MyApp Inherits Application End Class
En revanche, les chiers Page1.xaml et Page1.xaml.vb hritent non plus dun objet de classe Window mais bien dun objet de la classe Page.
<Page x:Class="Page1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1" > <Grid> </Grid> </Page> Imports Imports Imports Imports Imports Imports Imports Imports System System.Windows System.Windows.Controls System.Windows.Data System.Windows.Documents System.Windows.Media System.Windows.Media.Imaging System.Windows.Navigation
Imports System.Windows.Shapes Interaction logic for Page1.xaml Partial Public Class Page1 Inherits Page Public Sub New() InitializeComponent() End Sub End Class
Il ny a en dnitive pas de diffrences notables. Pour changer les noms des classes et des chiers, vous devez utiliser
Renvoi la technique dcrite dans le paragraphe Crer une application
Inherits Page Public Sub New() InitializeComponent() End Sub Public Sub Click_Repondre(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.lblTexte.Content = "Merci" Me.btnRepondre.IsEnabled = False End Sub End Class
Lapplication est trs semblable lapplication Windows mais elle est bien excute dans le navigateur. Si nous cliquons sur le bouton Rpondre, lapplication ragit comme prvu.
Erreur de scurit Si vous utilisez une version express de Visual Studio, vous recevrez peut-tre une erreur de scurit lors de la premire excution. Fermez puis rouvrez votre projet et lerreur disparatra delle-mme.
Si dans votre page vous ne devez pas utiliser de mthode, vous pouvez opter pour une page XAML seule. Il sagit alors dune page statique. Le code XAML sera directement excut lors du chargement de la page. Faites un copier-coller du code XAML dans NotePad. Supprimez lattribut Class et lattribut Click an dobtenir le code suivant :
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1" > <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Label Name="lblTexte"> Bonjour le monde. </Label> <Button Name="btnRepondre"> Rpondre </Button> </StackPanel> </Page>
Sauvez le document et, depuis lExplorateur Windows, double-cliquez dessus ou tapez son adresse dans Internet Explorer. La mme page est charge mais, bien entendu, le bouton neffectue plus aucune action. Comme il est possible de modier la taille dune fentre Windows, il est galement possible de modier la taille de la page mais aussi de la fentre du navigateur. Les attributs WindowWidth et WindowHeight permettent de contrler la taille de la fentre du navigateur alors que les attributs Width et Height contrlent la taille de la page. Modiez les valeurs de ces attributs dans lexemple ci-dessous pour bien comprendre leur porte.
<Page x:Class="Page1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1" WindowTitle="Ma page"
146 Le guide du codeur
<Border BorderThickness="1" BorderBrush="Black"> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Label Name="lblTexte"> Bonjour le monde. </Label> <Button Name="btnRepondre" Click="Click_Repondre"> Rpondre </Button> </StackPanel> </Border> </Page>
>
Titre de la fentre Le titre de la fentre est donn non pas par lattribut Title de la balise Page mais bien par lattribut WindowTitle.
La page tant entirement statique, il est inutile de crer une contre-partie VB. videmment, si votre seconde page est plus labore, rien nempche de crer une page complte avec du contenu XAML et .NET. Maintenant, voyons comment raliser lappel de cette page depuis le code .NET de notre premire page.
Public Sub Click_Repondre(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.NavigationService.Navigate(New Uri("Page2.xaml", UriKind.Relative)) End Sub
Lappel la page se fait comme prcdemment dans lvnement Click associ au bouton en utilisant la mthode Navigate de la proprit NavigationService. Cette mthode reoit comme paramtre une URI qui donne ladresse de la page afficher. LURI peut tre absolue ou relative.
Barre de navigation dInternet Explorer Notez que la barre de navigation du navigateur ne permet pas de raliser les habituelles oprations Prcdente, Suivante. Vous devez pour cela utiliser la barre de navigation spcique. b Figure 5-18 : Barre de navigation
Si vous ne souhaitez pas voir apparatre la barre de navigation, il suffit dassigner False lattribut ShowsNavigationUI de la balise Page.
148 Le guide du codeur
NavigationService dispose galement des mthodes GoBack et GoForward pour provoquer un passage la page prcdente ou la page suivante. Les mthodes CanGoBack et CanGoForward vous informent sur la possibilit ou non dappeler les mthodes respectives.
Il ny a pas grand-chose dire sur cette classe. Elle servira pour le transfert de donnes entre les pages. La premire page qui est automatiquement charge lors du dmarrage de lapplication est une page classique qui hrite de Page.
<Page x:Class="Page1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1" > <StackPanel> <Label Name="valeur"/> <Label Name="texte"/> <Button Name="btnPageSuiv" Click="PageSuivante"> Page suivante </Button> </StackPanel> </Page>
Dans le chier Page1.xaml, deux Label sont dnies mais sont vierges. Elles serviront afficher les valeurs reues. Le bouton sert demander la navigation vers la page suivante. Lappel se fera dans la mthode PageSuivante.
Partial Public Class Page1 Inherits Page
Dans le code .NET associ, nous dclarons un membre du type de la page qui sera appel. Il est important de dclarer que la page se mettra lcoute des vnements, ce qui est ralis avec WithEvents.
Private WithEvents pageSuiv As Page2 Public Sub New() InitializeComponent() End Sub Sub PageSuivante(ByVal sender As Object, ByVal e As RoutedEventArgs)
La transmission des paramtres la page se fait par le constructeur. Lappel de la page elle-mme se fait exactement comme une page normale.
pageSuiv = New Page2("dfaut") Me.NavigationService.Navigate(pageSuiv) End Sub
Il faut dnir la mthode qui sera appele lors du retour. Pour quelle soit effectivement appele, il faut lassocier lvnement avec Handles. Notez que
150 Le guide du codeur
Les valeurs reues sont places dans les contrles Label et le bouton est dsactiv.
valeur.Content = e.Result.Texte texte.Content = e.Result.Val btnPageSuiv.IsEnabled = False End Sub End Class
Nous devons maintenant dnir la page 2, qui sera une PageFunction. Notez la dnition du type de paramtre et la prsence de la dclaration du namespace de lapplication. Le namespace tant dans lassembly du programme, il nest pas ncessaire de prciser lassembly. La TextBox recevra la valeur reue en paramtre, qui pourra ainsi tre modie. La mthode associe lvnement Click du bouton aura pour effet de fermer la page.
<PageFunction x:Class="Page2" x:TypeArguments="app:Data" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:app="clr-namespace:WinFxBrowserApplication1" Title="Page2" > <StackPanel> <TextBox Name="texte"/> <Button Click="Fin"> Fin </Button> </StackPanel> </PageFunction>
Mme dans le code .NET, ds la dclaration de la page, il faut dcrire les paramtres reus.
Partial Public Class Page2 Inherits PageFunction(Of Data) Private donne As New Data
Pour fermer la fentre et revenir la page appele, on utilise OnReturn, qui doit imprativement retourner un objet de type ReturnEventArgs qui est un type gnrique.
Sub Fin(ByVal sender As Object, ByVal e As RoutedEventArgs) donne.Texte = texte.Text Dim retour As New ReturnEventArgs(Of Data)(donne) OnReturn((retour) End Sub End Class
Aprs avoir cliqu sur le bouton, la deuxime page est affiche. Et nous pouvons changer la valeur dans la bote de texte.
Aprs avoir cliqu sur le bouton de n, la premire page est nouveau affiche.
Il est galement possible dutiliser cette technique dans un Frame. Vous pouvez par exemple raliser une fentre complte avec un menu et divers lments qui doivent perdurer tout au long de la navigation et utiliser le Frame comme zone daffichage des diffrents contenus. En somme, il sagit dun genre de page matre. Pour illustrer cela, imaginons que notre page de dmarrage est la page StartPage dcrite ci-dessous.
<Page x:Class="StartPage" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="StartPage" > <DockPanel VerticalAlignment="Top"> <Image DockPanel.Dock="Top" Source="c:\photo.jpg" MinWidth="300"> </Image> <Menu DockPanel.Dock="Top" Height="30"> <MenuItem Header="Page 1" Click="GoToPage1"/> <MenuItem Header="Page 2" Click="GoToPage2"/> <MenuItem Header="Page 3" Click="GoToPage3"/> </Menu> <StatusBar DockPanel.Dock="Bottom" Background="LightBlue"> <Label> Micro Application </Label>
Il sagit dune page classique dont le menu servira naviguer et contenant un Frame qui reoit HomePage.xaml, dont le contenu est en dnitive la page daccueil.
Partial Public Class StartPage Inherits Page Public Sub New() InitializeComponent() End Sub Sub GotoPage1(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim nvPage As New Page1 zoneContenu.Navigate(nvPage) End Sub Sub GotoPage2(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim nvPage As New Page2 zoneContenu.Navigate(nvPage) End Sub Sub GotoPage3(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim nvPage As New Page3 zoneContenu.Navigate(nvPage) End Sub End Class
Si nous examinons le code .NET de la page, nous pouvons constater qu chaque action du menu une nouvelle page est affiche en provoquant la navigation dans le Frame uniquement. Notre page matre reste donc bel et bien toujours affiche.
coute des vnements Contrairement lexemple prcdent, le programme appelant ne se met pas lcoute de la valeur de retour car, dans cet exemple, elle ne nous intresse pas. Rien nempche de la faire si tel est le besoin.
La page daccueil HomePage.xaml est galement une page tout fait classique.
<Page x:Class="HomePage" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel> <Label> Ceci est la page principale </Label> </StackPanel> </Page>
Examinons maintenant la classe Page1. Page2 et Page3 sont construites sur le mme modle.
<PageFunction x:Class="Page1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" x:TypeArguments="sys:String" > <StackPanel> <Label> Ceci est la page 1 </Label> <Button Click="Retour"> Retour </Button> </StackPanel> </PageFunction>
Rfrence au namespace System Notez la prsence dune rfrence au namespace System et lassembly mscorlib pour pouvoir dnir le type String comme argument.
Partial Public Class Page1 Inherits PageFunction(Of String) Public Sub New() InitializeComponent() End Sub Sub Retour(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim retour As New ReturnEventArgs(Of String)("De Page1")
Le code .NET est galement extrmement simple. La seule chose noter est la prsence de OnReturn, dont nous avons vu prcdemment le fonctionnement. Lors du lancement du programme, la page daccueil est affiche.
Si dans le menu vous choisissez Menu1, la page 1 est son tour affiche mais dans le Frame, laissant tout le contexte inchang.
Particularit de navigation Si au lieu de cliquer sur Retour vous demandez une autre page dans le menu, par exemple pour demander la page 3, celle-ci saffiche sans problme mais, dans le cas o vous cliquez ce moment sur Retour, cest non pas la page daccueil qui est affiche mais bien la page 1, page qui est en ralit la base de lappel de la PageFunction.
Si vous souhaitez que la page daccueil soit systmatiquement raffiche, il vous suffit de vous mettre lcoute de la valeur de retour, comme nous lavons fait dans le premier exemple ; et, dans la mthode qui traite le retour, vous pouvez imposer dafficher la page daccueil dans le Frame. Cette faon de travailler apporte normment de souplesse. Rien ne vous empche par exemple de travailler avec plusieurs Frame. Finalement, le modle en page peut facilement suivre un comportement semblable aux applications Windows classiques. Noubliez toutefois pas que lutilisateur peut galement utiliser la barre de navigation.
<NavigationWindow x:Class="Window1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Ma premire application Windows en mode page" Source="Page1.xaml" />
Window1.xaml.vb Dans lexemple, ce chier est inutile et peut tre effac. Si vous dsirez le conserver, vous devrez modier lhritage de la classe pour y faire apparatre NavigationWindow en lieu et place de Window.
Lutilisation dune application WBA en tant quapplication Windows client nest pas la seule utilit de NavigationWindow. Cette faon de travailler est aussi trs utile pour raliser un assistant Wizard, par exemple. Il sagit non plus alors dune application complte faite sur ce modle mais uniquement dune partie
158 Le guide du codeur
de celle-ci. Le reste de lapplication tant classiquement compos de fentres de type Window simple. Voici un exemple extrmement simpli. Tout dabord, la fentre classique, qui fait appel lassistant via un bouton, mais cela peut tout aussi bien tre un menu.
<Window x:Class="ClassicWindow" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Label Name="lblTexte"> Fentre classique. </Label> <Button Name="btnWizard" Click="Wizard"> Wizard </Button> </StackPanel> </Window> Imports Imports Imports Imports Imports Imports Imports Imports System System.Windows System.Windows.Controls System.Windows.Data System.Windows.Documents System.Windows.Media System.Windows.Media.Imaging System.Windows.Shapes
Interaction logic for Window1.xaml Partial Public Class HelloWorld Inherits Window Public Sub New() InitializeComponent() End Sub Public Sub Wizard(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim wiz As New Window1 wiz.ShowDialog() End Sub End Class
La mthode Wizard qui est associe lvnement Click du bouton instancie et affiche une fentre de type Window1. Comme vous pouvez le constater dans ce qui suit, Window1 est une fentre de type NavigationWindow.
<NavigationWindow x:Class="Window1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Mon premier wizard" Source="Page1.xaml" Width="280" Height="160" />
Interaction logic for Page1.xaml Partial Public Class Page1 Inherits Page Public Sub New() InitializeComponent() End Sub Public Sub Prec(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.NavigationService.GoBack() End Sub Public Sub Suiv(ByVal sender As Object _ , ByVal e As RoutedEventArgs) If Me.radA.IsChecked Then Me.NavigationService.Navigate( _ New Uri("Page1A.xaml", UriKind.Relative)) Else Me.NavigationService.Navigate( _ New Uri("Page1B.xaml", UriKind.Relative)) End If End Sub End Class
Notez que le bouton Retour dclenche la mthode GoBack de la fentre de navigation tout comme si vous aviez appuy sur la che [Retour}Arrire]. Si nous choisissons loption A, la mthode nous fait naviguer vers la page Page1A.xaml.
<Page x:Class="Page1A" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1A" > <StackPanel>
Le guide du codeur 161
<RadioButton Name="rad1" MaxWidth="50" Margin="5,5,5,5"> 1. </RadioButton> <RadioButton Name="rad2" MaxWidth="50" Margin="5,5,5,5"> 2. </RadioButton> <WrapPanel HorizontalAlignment="Center"> <Button Width="80" Margin="5,5,5,5" Click="Prec"> Retour </Button> <Button Width="80" Margin="5,5,5,5" Click="Suiv"> Suivant </Button> </WrapPanel> </StackPanel> </Page> Imports Imports Imports Imports Imports Imports Imports Imports Imports System System.Windows System.Windows.Controls System.Windows.Data System.Windows.Documents System.Windows.Media System.Windows.Media.Imaging System.Windows.Navigation System.Windows.Shapes
Partial Public Class Page1A Inherits Page Public Sub New() InitializeComponent() End Sub Public Sub Prec(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.NavigationService.GoBack() End Sub Public Sub Suiv(ByVal sender As Object _ , ByVal e As RoutedEventArgs) If Me.rad1.IsChecked Then Me.NavigationService.Navigate( _ New Uri("Page1A1.xaml", UriKind.Relative)) Else Me.NavigationService.Navigate( _
162 Le guide du codeur
Interaction logic for Page1.xaml Partial Public Class Page1A2 Inherits Page Public Sub New() InitializeComponent() End Sub Public Sub Prec(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.NavigationService.GoBack() End Sub Public Sub Terminer(ByVal sender As Object _ , ByVal e As RoutedEventArgs) DirectCast(Me.Parent, NavigationWindow).Close() End Sub End Class
Pour fermer la fentre, il est ncessaire de convertir la proprit Parent en une NavigationWindow que nous savons quelle est. Si nous demandons le retour en arrire, les ches avant et arrire deviennent accessibles.
Boutons de navigation La fentre ne rend accessibles les boutons de navigation que si la navigation dans ce sens est possible. Vous pouvez galement connatre cette information en utilisant les proprits CanGoBack et CanGoForward.
Comme vous pouvez le constater, XAML pourra interagir avec le JavaScript mais galement excuter du code intermdiaire (compil) .NET. Ce dernier pourra tre excut directement par lAdd-in. Le code XAML pourra tre intgr la page HTML ou utilis comme une ressource externe. Voici tout dabord comment devrait se prsenter une page avec une application WPF/E en ressource externe.
<html> <body> <object id="wpfehost" size=""> <param name=source value=monAppliction.wpfe/> </body> </html>
Lapplication WPF/E contiendra le XAML compress (baml) mais aussi le code IL (.NET compil) et les ressources (images, mdia...). Maintenant, voyons comment devrait se prsenter une application WPF/E intgre la page HTML.
<html> <head> <!Script XAML--> <script id="monScriptXaml" type="text/xaml"> <? Xml version="1.0" ?>
Checklist
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> ... </Canvas> </script> </head> <body> ... <object id="wpfe" classid="..." codebase="xcpctrl.cab#version=0,0,3,0" height="300" width="400"> <param name="SourceElement" value="monScriptXaml"/> <param name="WindowslessMode" value="True"/> <param name="BackgroundColor value="#00000000"/> </object> ... </body> </html>
Comme vous lavez vu dans le diagramme darchitecture, vous pouvez manipuler des objets WPF/E depuis le code JavaScript. Voici en quelques lignes comment faire.
<script type="text/javascript"> void Fuction maFonction() { var wpfeObject = document.getElementById("wpfe") ; var ctrl = wpfeObject.FindName("LeNomDeMonControleDansXAML") ; ctrl.SetValue("NomDeLaProprit", valeur) ; } </script>
Vous pouvez par ce moyen crer des pages qui utilisent la fois le HTML, le JavaScript et WPF/E au travers de XAML et si ncessaire de code .NET. Ces technologies peuvent non seulement cohabiter mais galement interagir.
5.7 Checklist
Dans ce chapitre essentiellement dirig sur la gestion dune application, nous avons vu :
j j
comment est compose une application Windows et comment la raliser ; comment raliser une application laquelle on accdera depuis un navigateur web (application WBA) ; comment utiliser PageFunction ;
Le guide du codeur 167
j j j
j j j
comment raliser une page matre pour naviguer dans lapplication ; comment grer la scurit pour les applications WBA ; comment transformer simplement une application WBA en application Windows ; comment raliser un assistant (Wizard) ; comment grer les vnements dans XAML ; les bases du futur modle dapplication WPF/E.
Ch apit re
6 Les menus
Crer un menu .......................................... Crer un menu contextuel ........................... Crer une barre doutils .............................. Checklist ..................................................
Les menus
Hauteur du menu La proprit Height est obligatoire sinon le menu occupera toute la hauteur disponible dans notre fentre.
Dans lexemple prcdent, la fentre principale ne pourra contenir que le menu. Cest toutefois le cas de beaucoup dapplications et essentiellement des applications MDI. Si tel nest pas votre objectif, la solution est simple et dj connue. Il nous suffit de placer le menu dans un conteneur tel quune grille, un StackPanel ou encore un DockPanel.
170 Le guide du codeur
Crer un menu
<Window xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Les menus avec XAML" > <DockPanel> <Menu VerticalAlignment="Top" Height="20" DockPanel.Dock="Top"> <MenuItem Header="Fichier"/> <MenuItem Header="Edition"/> <MenuItem Header="Aide"/> </Menu> </DockPanel> </Window>
Le rsultat sera identique, la diffrence prs quil est maintenant possible de placer dautres contrles ou dautres conteneurs dans la fentre.
Les sous-menus
Pour crer un sous-menu, un menu vertical, il suffit de dnir un ou des MenuItem dans le nud MenuItem du menu principal. Chaque nouveau MenuItem peut son tour contenir dautres MenuItem ls.
<Window xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Les menus avec XAML" > <DockPanel> <Menu VerticalAlignment="Top" Height="20" DockPanel.Dock="Top"> <MenuItem Header="Fichier"> <MenuItem Header="Ouvrir"/> <MenuItem Header="Fermer"/> </MenuItem> <MenuItem Header="Edition"> <MenuItem Header="Copier"/> <MenuItem Header="Coller"/> <Separator /> <MenuItem Header="Livre"> <MenuItem Header="Prcdent"/> <MenuItem Header="Suivant"/> </MenuItem> </MenuItem> <MenuItem Header="Aide"/> </Menu>
Le guide du codeur 171
Les menus
</DockPanel> </Window>
Placer des sparations dans le menu Notez lutilisation de la balise Separator pour crer un sparateur.
Crer un menu
Raliser soi-mme lexemple Si vous souhaitez reproduire cet exemple, vous devrez crer un projet dans Visual Studio.
Les menus
<Menu VerticalAlignment="Top" Height="20" DockPanel.Dock="Top"> <MenuItem Header="Fichier"> <MenuItem Name="mnuOuvrir" Header="Ouvrir" Click="Click_Ouvrir"/> <MenuItem Name="mnuFermer" Header="Fermer" IsEnabled="False" Click="Click_Fermer"/> </MenuItem> <MenuItem Header="Edition"> <MenuItem Header="Copier"/> <MenuItem Header="Coller"/> <Separator /> <MenuItem Header="Livre"> <MenuItem Header="Prcdent"/> <MenuItem Header="Suivant"/> </MenuItem> </MenuItem> <MenuItem Header="Aide"> <MenuItem Name="mnuEnLigne" Header="En ligne" IsChecked="True" Click="Click_EnLigne"/> </MenuItem> </Menu> </DockPanel> </Window>
Importance des noms Jusqu maintenant, dans les menus, je navais pas pris la peine de donner des noms. Comme vous pouvez le constater, cela se rvle rapidement ncessaire.
Les mthodes qui seront appeles lors des vnements Click respectifs sont dnies dans le code VB.NET associ.
Imports Imports Imports Imports Imports Imports Imports Imports System System.Windows System.Windows.Controls System.Windows.Data System.Windows.Documents System.Windows.Media System.Windows.Media.Imaging System.Windows.Shapes
Interaction logic for Window1.xaml Partial Public Class Window1 Inherits Window
Crer un menu
Public Sub New() InitializeComponent() End Sub Public Sub Click_Ouvrir(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = True Me.mnuOuvrir.IsEnabled = False End Sub Public Sub Click_Fermer(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = False Me.mnuOuvrir.IsEnabled = True End Sub Public Sub Click_EnLigne(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuEnLigne.IsChecked = _ Not Me.mnuEnLigne.IsChecked End Sub End Class
La syntaxe dcriture des mthodes appeles par les vnements est tout fait conforme ce que nous avons vu dans le chapitre rserv ce sujet.
Problme avec lIntelliSense Actuellement, lIntelliSense ne reconnat pas directement les noms que nous avons ajouts. Recompilez votre projet et ceux-ci apparatront.
Pour changer notre menu, nous devons simplement modier les proprits IsChecked et IsEnabled qui correspondent aux attributs du mme nom.
Inverser une valeur Nous ne devons pas connatre ltat de IsChecked pour cocher ou dcocher llment En ligne du menu. Il suffit dinverser la valeur pour obtenir le rsultat souhait, ce qui se fait simplement en rassignant la valeur elle-mme et en la prcdant de Not.
Les menus
Comme vous pouvez le constater, tous les lments du menu sont maintenant nomms, ce qui nous permettra daccder nimporte lequel des lments. Un autre attribut important a galement t ajout. Lattribut Visibility permet de cacher ou dafficher un lment. Il peut prendre trois valeurs diffrentes.
Crer un menu
j j j
visible : llment est affich. hidden : llment nest pas affich mais sa place est rserve. collapsed : llment nest pas affich et sa place nest pas rserve, ce qui provoque un dplacement des autres lments du menu.
Interaction logic for Window1.xaml Partial Public Class Window1 Inherits Window Public Sub New() InitializeComponent() End Sub Public Sub Click_Ouvrir(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = True Me.mnuOuvrir.IsEnabled = False Me.mnuEdition.Visibility = Windows.Visibility.Visible End Sub Public Sub Click_Fermer(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = False Me.mnuOuvrir.IsEnabled = True Me.mnuEdition.Visibility = _ Windows.Visibility.Collapsed End Sub Public Sub Click_EnLigne(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuEnLigne.IsChecked = Not Me.mnuEnLigne.IsChecked End Sub End Class
Les menus
Mais, aprs avoir cliqu sur Ouvrir, le menu Edition est ajout.
Grce lutilisation de la proprit Visibility, le code .NET est Cela ncessite de penser compltement le menu dans le module vous tes amen ajouter un menu de manire totalement cest--dire sans quil soit prvu initialement, vous devrez le faire au moyen de code .NET.
Title="Les menus avec XAML" > <DockPanel> <Menu Name="mnuMain" VerticalAlignment="Top" Height="20" DockPanel.Dock="Top"> <MenuItem Name="mnuFichier" Header="Fichier"> <MenuItem Name="mnuOuvrir" Header="Ouvrir" Click="Click_Ouvrir"/> <MenuItem Name="mnuFermer" Header="Fermer" IsEnabled="False" Click="Click_Fermer"/> </MenuItem> <MenuItem Name="mnuEdition" Header="Edition" Visibility="Collapsed"> <MenuItem Name="mnuCopier" Header="Copier"/> <MenuItem Name="mnuColler" Header="Coller"/> <Separator /> <MenuItem Name="mnuLivre" Header="Livre"> <MenuItem Name="mnuPrec" Header="Prcdent" Click="Click_Prev"/> <MenuItem Name="mnuSuiv" Header="Suivant" Click="Click_Next"/> </MenuItem> </MenuItem> <MenuItem Header="Aide"> <MenuItem Name="mnuEnLigne" Header="En ligne" IsChecked="True" Click="Click_EnLigne"/> </MenuItem> </Menu> <Canvas Name="frmData" IsEnabled="False" Background="LightBlue" DockPanel.Dock="Bottom"> <Canvas.ContextMenu> <ContextMenu> <MenuItem Header="Prcdent" Click="Click_Prev"/> <MenuItem Header="Suivant" Click="Click_Next"/> </ContextMenu> </Canvas.ContextMenu> <Label Name="lblNom" Canvas.Top="10" Canvas.Left="10"> Nom </Label> <TextBox Name="txtNom" Canvas.Top="10" Canvas.Left="80" Width="150" MaxLength="30" CharacterCasing="Upper" /> <Label Name="lblPrenom" Canvas.Top="10" Canvas.Left="240"> Prnom
Le guide du codeur 179
Les menus
</Label> <TextBox Name="txtPrenom" Canvas.Top="10" Canvas.Left="300" Width="130" MaxLength="30"/> <Label Name="lblAdr" Canvas.Top="40" Canvas.Left="10"> Rue </Label> <TextBox Name="txtAdr" Canvas.Top="40" Canvas.Left="80" Width="350" MaxLength="80"/> <Label Name="lblCP" Canvas.Top="70" Canvas.Left="10"> Code postal </Label> <TextBox Name="txtCP" Canvas.Top="70" Canvas.Left="80" Width="50" MaxLength="5"/> <Label Name="lblLocalite" Canvas.Top="70" Canvas.Left="150"> Localit </Label> <TextBox Name="txtLocalite" Canvas.Top="70" Canvas.Left="200" Width="230" MaxLength="50"/> <Border Width="100" Height="120" BorderThickness="1" Background="White" BorderBrush="Black" Canvas.Top="10" Canvas.Right="10"> <TextBlock Name="blkPhoto" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"> Photo </TextBlock> </Border> <Label Name="lblCopyright" Canvas.Bottom="10" Canvas.Right="10" Content="Micro Application 2006" /> </Canvas> </DockPanel> </Window>
Public Sub Click_Ouvrir(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = True Me.mnuOuvrir.IsEnabled = False Me.mnuEdition.Visibility = Windows.Visibility.Visible Me.frmData.IsEnabled = True End Sub Public Sub Click_Fermer(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = False Me.mnuOuvrir.IsEnabled = True Me.mnuEdition.Visibility = Windows.Visibility.Collapsed Me.frmData.IsEnabled = False End Sub Public Sub Click_EnLigne(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuEnLigne.IsChecked = Not Me.mnuEnLigne.IsChecked End Sub Public Sub Click_Prev(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Code pour prcedent End Sub Public Sub Click_Next(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Code pour suivant End Sub End Class
Les menus
Si vous essayez dactiver le menu contextuel, rien ne se passe. Le menu nest pas accessible car le canevas est dsactiv. Lactivation du canevas est ralise dans la mthode Click_Ouvrir. Aprs avoir effectu Fichier, Ouvrir, le menu contextuel est maintenant actif.
Toutefois, les botes de texte conservent leur menu contextuel par dfaut.
Si vous dsirez les remplacer, il faudra crer un autre menu contextuel. Remplacez le premier TextBox par celui-ci et il possdera son propre menu contextuel. videmment, dans lexemple, il est trs simpli. Aucune action ne lui est associe mais cela, vous savez dj comment le rsoudre.
<TextBox Name="txtNom" Canvas.Top="10" Canvas.Left="80" Width="150" MaxLength="30" CharacterCasing="Upper"> <TextBox.ContextMenu> <ContextMenu> <MenuItem Header="Copier"/> <MenuItem Header="Coller"/> </ContextMenu> </TextBox.ContextMenu> </TextBox>
Les menus
Positionnement de la barre doutils Nous avons ici utilis un DockPanel pour placer la barre doutils et le menu, mais nous aurions tout aussi bien pu utiliser une grille, un StackPanel ou mme un WrapPanel. Le canevas est quant lui moins appropri, mais pourquoi pas !
La barre doutils peut contenir dautres contrles que le bouton. Par exemple une ComboBox.
<ToolBar DockPanel.Dock="Top" Height="24"> <Button ToolTip="Ouvrir" Click="Click_Ouvrir"> <Image> <Image.Source> <Binding Source="open.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Fermer" Click="Click_Fermer"> <Image> <Image.Source> <Binding Source="close.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Precedent"> <Image> <Image.Source>
<Binding Source="precedent.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Suivant"> <Image> <Image.Source> <Binding Source="suivant.bmp"/> </Image.Source> </Image> </Button> <Separator/> <ComboBox Width="80"> <ComboBoxItem IsSelected="True"> Par nom </ComboBoxItem> <ComboBoxItem> Par localit </ComboBoxItem> </ComboBox> </ToolBar>
Sparateur La ComboBox est prcde dun sparateur. Il ne sagit absolument pas dune obligation. Vous pouvez placer des sparateurs o bon vous semble simplement en y plaant la balise Separator comme dans le code ci-dessus.
Les menus
redimensionner votre guise les diffrentes barres doutils. Avec XAML, nous pouvons crer un conteneur dans lequel nous allons placer nos barres doutils. Elles pourront tre alors dplaces ou redimensionnes par lutilisateur dans lespace dtermin par le conteneur. Si lutilisateur rduit trop la taille dune barre doutils, les lments qui ne sont plus affichables sont automatiquement ajouts dans une zone de dpassement et rendus accessibles via la petite che qui marque la n de la barre doutils. Pour crer un conteneur, vous devez utiliser la balise ToolBarTray.
<ToolBarTray DockPanel.Dock="Top" IsLocked="False" Background="LightGray"> <ToolBar Band="0" Height="24"> <Button ToolTip="Ouvrir" Click="Click_Ouvrir"> <Image> <Image.Source> <Binding Source="open.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Fermer" Click="Click_Fermer"> <Image> <Image.Source> <Binding Source="close.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Precedent"> <Image> <Image.Source> <Binding Source="precedent.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Suivant"> <Image> <Image.Source> <Binding Source="suivant.bmp"/> </Image.Source> </Image> </Button> </ToolBar> <ToolBar Band="1" Height="24"> <ComboBox Width="80"> <ComboBoxItem IsSelected="True"> Par nom </ComboBoxItem> <ComboBoxItem> Par localit
Vous pouvez constater que la barre doutils prcdemment cre a t scinde en deux au niveau du sparateur. Cest maintenant la ToolBarTray qui reoit lattribut DockPanel.Dock. Pour viter un fond blanc, lattribut Background reoit la valeur LightGray. Lattribut Band dans la balise ToolBar permet de xer le numro de ligne dans lequel vous dsirez voir apparatre la barre doutils.
Lutilisateur peut dplacer les barres doutils, soit pour les rassembler sur une mme ligne, soit pour les inverser. Il ne pourra en revanche pas les dcaler vers la gauche en laissant un espace entre les barres doutils.
Bloquer les barres doutils La proprit IsLocked permet de spcier si les barres doutils contenues sont mobiles ou non. Il est possible de le spcier individuellement pour chaque barre en introduisant dans la balise de la barre concerne lattribut ToolBarTray.IsLocked.
Si vous souhaitez afficher la barre doutils gauche plutt quen haut de lcran, cest trs simple. Vous changez lattribut Orientation et cest pratiquement tout.
<ToolBarTray DockPanel.Dock="Left" IsLocked="False" Background="LightGray" Orientation="Vertical">
Le guide du codeur 187
Les menus
En effet, il est galement judicieux de changer le docking, sans quoi le rsultat ne sera pas celui espr.
Ordre des lignes Vu le changement dorientation, les lignes dnies par lattribut Band deviennent des colonnes. Cest pourquoi il est prfrable dans notre exemple de xer la valeur 0 pour les deux barres doutils.
<ToolBar Band="0">
Hauteur des lignes Pour les mmes raisons, la hauteur qui tait xe 24 points doit tre adapte pour par exemple devenir automatique. Pour y arriver, retirez lattribut Height de chaque balise ToolBar.
Avec ces barres doutils ottantes, nous devons nous pencher dun peu plus prs sur la zone de dbordement. Si vous rduisez la taille de la premire barre doutils en montant la seconde, la zone de dbordement indique par la che maintenant noire et non plus grise est active. Malheureusement, si vous tentez de lutiliser, licne cache va bel et bien safficher mais en trs grand. Pour viter ce problme, il est prudent dutiliser les attributs MaxWidth et MaxHeigth des images des diffrents boutons. Les autres contrles ventuels doivent subir le mme traitement.
<Image MaxHeight="24" MaxWidth="24">
Checklist
Si vous souhaitez changer lordre des barres doutils sans dplacer tout le code, vous pouvez simplement utiliser lattribut BandIndex. Dans lexemple, assignez 1 cet attribut pour la premire barre doutils.
ToolBar Band="0" BandIndex="1">
6.4 Checklist
Dans ce chapitre, nous avons vu comment crer et manipuler les menus et particulirement comment :
j j j j
crer un menu dapplication complet avec sous-menu et menus imbriqus ; rendre un menu dynamique ; crer un menu contextuel ; crer et manipuler une barre doutils.
Le guide du codeur 189
Ch apit re
Outre la possibilit dassigner vous-mme les valeurs aux diffrents contrles, vous aurez certainement envie de mettre en place des techniques comme la liaison aux donnes (Data Binding) pour lier vos contrles avec les donnes qui doivent y tre reprises. Cette technique nest pas neuve mais nous allons voir comment la mettre en uvre avec XAML.
Une fois la base de donnes cre, nous devons lajouter notre projet. Choisissez dans le menu de Visual Studio Donnes - Ajouter une nouvelle
source de donnes
Si ce nest dj fait, choisissez loption Base de donnes et cliquez sur Suivant. Cliquez sur le bouton Nouvelle connexion et ensuite sur le bouton Modier.
Cliquez maintenant sur le bouton Parcourir, choisissez la base de donnes que vous venez de crer et cliquez sur OK puis sur Suivant.
Le DataSet est maintenant cr. Il ne nous reste qu linclure dans notre programme. Modiez le code de Window1.xaml.vb pour reter le code ci-dessous.
Private m_data As New DBXAMLDataSet Private m_i As Integer Public Sub New() InitializeComponent() Dim adapter As New _ DBXAMLDataSetTableAdapters.Carnet_adressesTableAdapter adapter.Fill(m_data.Carnet_adresses) End Sub
Une fois cette tape ralise, nous devons maintenant associer le DataSet notre fentre. Commenons par ajouter la gestion de lvnement Loaded de la fentre.
<Window x:Class="Window1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Les menus avec XAML" Loaded="Win_loaded" >
La mthode Win_loaded est appele aprs le chargement de la fentre. Dans cette mthode, nous allons initialiser la source de donnes.
Private Sub Win_loaded(ByVal sender As Object _ , ByVal e As RoutedEventArgs) m_i = 0 Me.DataContext = m_data.Carnet_adresses.Rows(m_i) End Sub
Liaison une ligne de la table En ralit, nous ne lions pas le DataSet dans son ensemble notre cran mais lions seulement une ligne dune table. En loccurrence, la premire ligne de la table Carnet adresses.
Il reste maintenant lier les champs avec les zones cran. Commenons par le nom.
194 Le guide du codeur
<TextBox Name="txtNom" Canvas.Top="10" Canvas.Left="80" Width="150" MaxLength="30" CharacterCasing="Upper" Text ="{Binding Path=Nom}">
Pour raliser la liaison, nous devons utiliser un objet de type Binding. Lobjet doit tre assign la proprit, qui doit tre lie. Pour y arriver, nous avons utilis une syntaxe un peu particulire. Nous pouvons dj excuter lapplication telle quelle.
Le nom est correctement affich lcran. Faisons de mme avec les autres champs. Pour vous aider reconstruire lexemple, vous trouverez ci-dessous le code complet que nous avons dj discut prcdemment.
<Window x:Class="Window1" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Les menus avec XAML" Loaded="Win_loaded" > <DockPanel> <Menu Name="mnuMain" VerticalAlignment="Top" Height="20" DockPanel.Dock="Top"> <MenuItem Name="mnuFichier" Header="Fichier"> <MenuItem Name="mnuOuvrir" Header="Ouvrir" Click="Click_Ouvrir"/> <MenuItem Name="mnuFermer" Header="Fermer" IsEnabled="False" Click="Click_Fermer"/> </MenuItem> <MenuItem Name="mnuEdition" Header="Edition" Visibility="Collapsed">
Le guide du codeur 195
<MenuItem Name="mnuCopier" Header="Copier"/> <MenuItem Name="mnuColler" Header="Coller"/> <Separator /> <MenuItem Name="mnuContact" Header="Contact"> <MenuItem Name="mnuPrec" Header="Prcdent" Click="Click_Prev"/> <MenuItem Name="mnuSuiv" Header="Suivant" Click="Click_Next"/> </MenuItem> </MenuItem> <MenuItem Header="Aide"> <MenuItem Name="mnuEnLigne" Header="En ligne" IsChecked="True" Click="Click_EnLigne"/> </MenuItem> </Menu> <ToolBarTray DockPanel.Dock="Left" IsLocked="False" Background="LightGray" Orientation="Vertical"> <ToolBar Band="0"> <Button ToolTip="Ouvrir" Click="Click_Ouvrir"> <Image MaxHeight="24" MaxWidth="24"> <Image.Source> <Binding Source="open.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Fermer" Click="Click_Fermer"> <Image MaxHeight="24" MaxWidth="24"> <Image.Source> <Binding Source="close.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Precedent" Click="Click_Prev"> <Image MaxHeight="24" MaxWidth="24"> <Image.Source> <Binding Source="precedent.bmp"/> </Image.Source> </Image> </Button> <Button ToolTip="Suivant" Click="Click_Next"> <Image MaxHeight="24" MaxWidth="24"> <Image.Source> <Binding Source=" suivant.bmp"/> </Image.Source> </Image> </Button> </ToolBar> <ToolBar Band="0">
196 Le guide du codeur
<ComboBox Width="80"> <ComboBoxItem IsSelected="True"> Par nom </ComboBoxItem> <ComboBoxItem> Par localit </ComboBoxItem> </ComboBox> </ToolBar> </ToolBarTray> <Canvas Name="frmData" IsEnabled="False" Background="LightBlue" DockPanel.Dock="Bottom"> <Canvas.ContextMenu> <ContextMenu> <MenuItem Header="Prcdent" Click="Click_Prev"/> <MenuItem Header="Suivant" Click="Click_Next"/> </ContextMenu> </Canvas.ContextMenu> <Label Name="lblNom" Canvas.Top="10" Canvas.Left="10"> Nom </Label> <TextBox Name="txtNom" Canvas.Top="10" Canvas.Left="80" Width="150" MaxLength="30" CharacterCasing="Upper" Text ="{Binding Path=Nom}"> <TextBox.ContextMenu> <ContextMenu> <MenuItem Header="Copier"/> <MenuItem Header="Coller"/> </ContextMenu> </TextBox.ContextMenu> </TextBox> <Label Name="lblPrenom" Canvas.Top="10" Canvas.Left="240"> Prnom </Label>
Cest partir dici que le code est effectivement modi. Pour chacun des TextBox un objet de type Binding est assign la proprit Text.
<TextBox Name="txtPrenom" Canvas.Top="10" Canvas.Left="300" Width="130" MaxLength="30" Text ="{Binding Path=Prenom}"/> <Label Name="lblAdr" Canvas.Top="40" Canvas.Left="10"> Rue
</Label> <TextBox Name="txtAdr" Canvas.Top="40" Canvas.Left="80" Width="350" MaxLength="80" Text ="{Binding Path=Adresse}"/> <Label Name="lblCP" Canvas.Top="70" Canvas.Left="10"> Code postal </Label> <TextBox Name="txtCP" Canvas.Top="70" Canvas.Left="80" Width="50" MaxLength="5" Text ="{Binding Path=CP}"/> <Label Name="lblLocalite" Canvas.Top="70" Canvas.Left="150"> Localit </Label> <TextBox Name="txtLocalite" Canvas.Top="70" Canvas.Left="200" Width="230" MaxLength="50" Text ="{Binding Path=Localite}"/> <Border Width="100" Height="120" BorderThickness="1" Background="White" BorderBrush="Black" Canvas.Top="10" Canvas.Right="10"> <Image Source="{Binding Path=Photo}"/> </Border> <Label Name="lblCopyright" Canvas.Bottom="10" Canvas.Right="10" Content="Micro Application 2006" /> </Canvas> </DockPanel> </Window>
Autres modications Au passage, la gestion des vnements Click a t ajoute dans la barre doutils pour faire appel aux mthodes Click_Next et Click_Prev.
En revanche, rien ne se passe si vous cliquez sur Suivant. Nous devons encore ajouter la gestion des changements denregistrement.
Public Sub Click_Prev(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Code pour prcedent If m_i > 0 Then m_i = m_i - 1 Me.DataContext = m_data.Carnet_adresses.Rows(m_i) End If End Sub Public Sub Click_Next(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Code pour suivant If m_i < m_data.Carnet_adresses.Rows.Count - 1 Then m_i = m_i + 1 Me.DataContext = m_data.Carnet_adresses.Rows(m_i) End If End Sub
Le champ m_i permet de conserver en mmoire la position courante dans la DataTable. Ce code intgre les instructions pour viter de dpasser les limites de la table. Comme vous pouvez le constater, il suffit dadapter le DataContext pour quil contienne la ligne voulue. Maintenant, lenregistrement change lorsque vous demandez le suivant ou le prcdent.
Idalement, il faudrait dsactiver les boutons Prcdent et Suivant des diffrents menus quand ceux-ci ne peuvent tre raliss.
Le guide du codeur 199
Vous pouvez modier une valeur dans lcran, changer denregistrement et revenir sur celui que vous avez modi, les modications sont toujours prsentes.
Enregistrement dans la base de donnes Les donnes sont bien sauves dans le DataSet mais le code en ltat nenregistre pas le DataSet dans la base de donnes. Les modications sont ds lors perdues au moment o vous quittez le programme.
Par exemple, nous pouvons enregistrer les donnes dans la base de donnes lors de lopration de fermeture. Modiez le code pour reter le code ci-dessous.
Private m_adapter As _ DBXAMLDataSetTableAdapters.Carnet_adressesTableAdapter Public Sub New() InitializeComponent() m_adapter = New _ DBXAMLDataSetTableAdapters.Carnet_adressesTableAdapter m_adapter.Fill(m_data.Carnet_adresses) End Sub Public Sub Click_Fermer(ByVal sender As Object _ , ByVal e As RoutedEventArgs) Me.mnuFermer.IsEnabled = False Me.mnuOuvrir.IsEnabled = True Me.mnuEdition.Visibility = _ Windows.Visibility.Collapsed Me.frmData.IsEnabled = False m_adapter.Update(m_data) End Sub
Nouveau champ dans la classe Lobjet m_adapter prcdemment dni comme variable locale dans le constructeur devient un champ de la classe. De cette faon, il peut tre utilis dans la mthode Click_Fermer.
Il est galement possible dutiliser une table pour charger un contrle de type liste. Si vous souhaitez reproduire lexemple, modiez votre base de donnes et recrez le schma XSD pour reter le graphique ci-dessous.
Non seulement nous chargeons le membre m_data avec la DataTable Carnet_adresses mais nous chargeons galement la table Pays. Private Sub Win_loaded(ByVal sender As Object _ , ByVal e As RoutedEventArgs) m_i = 0 Me.DataContext = m_data.Carnet_adresses.Rows(m_i) Me.lstPays.DataContext = m_data End Sub
La table Pays est maintenant charge dans le DataSet et le DataContext de la liste est diffrent de celui du reste de lcran. Ajoutez ces balises dans le code XAML.
<Label Canvas.Top="100" Canvas.Left="150"> Pays </Label> <ListBox Name="lstPays" Canvas.Top="100" Canvas.Left="200" ItemsSource="{Binding Path=Pays}" DisplayMemberPath="Pays"/>
Remarquez que la source est non pas un champ mais une table. Cest lattribut DisplayMemberPath qui prcise le nom du champ afficher. Dans cet exemple, le nom est le mme car il sagit du champ Pays dans la table Pays.
Cette solution fonctionne parfaitement pour charger la liste mais, du coup, il ne nous est pas possible de lier la valeur notre carnet dadresses. La solution la plus simple est de modier nouveau le code .NET.
Private Sub Win_loaded(ByVal sender As Object _ , ByVal e As RoutedEventArgs) m_i = 0 Me.DataContext = m_data.Carnet_adresses.Rows(m_i) Dim bind As New Binding("Pays") bind.Source = m_data Me.lstPays.SetBinding(ListBox.ItemsSourceProperty _ , bind) End Sub
De cette faon, une source spcique est dnie pour la liste et la source par dfaut pour la valeur. Cet exemple dmontre non seulement quil est possible de raliser des liaisons vers divers objets mais galement que la liaison peut tre effectue sur diffrents attributs. Vous pourriez par exemple dnir une liaison sur la couleur du fond.
Public Property Nom() As String Get Return m_nom End Get Set(ByVal value As String) m_nom = value.ToUpper() End Set
End Property Public Property Prenom() As String Get Return m_prenom End Get Set(ByVal value As String) m_prenom = valueli End Set End Property
Comme vous pouvez le voir, il sagit essentiellement de dnir des membres privs et les proprits qui leur sont associes. Vous pourriez tre tent de dnir directement les membres comme publics et ainsi de vous passer des proprits. Toutefois, il vaut mieux suivre ds le dpart les bonnes pratiques et respecter cette rgle qui apportera dans lvolution de votre classe beaucoup plus de souplesse. Sans compter que le membre dni peut pour des raisons mtier ou techniques tre stock dune certaine manire et prsent aux utilisateurs de la classe dune autre faon.
Public Property Adresse() As String Get Return m_adresse End Get Set(ByVal value As String) m_adresse = value End Set End Property Public Property CP() As String Get Return m_cp End Get Set(ByVal value As String) m_cp = value End Set End Property Public Property Localite() As String Get Return m_localite End Get Set(ByVal value As String) m_localite = value End Set End Property
Public Property Pays() As Integer Get Return m_pays End Get Set(ByVal value As Integer) m_pays = value End Set End Property
Pour une question de simplicit, la mthode de chargement des donnes est incluse dans lobjet Business. Il existe beaucoup de techniques diffrentes pour raliser les couches, mais nous entrons l dans des problmes darchitecture bien loigns de ce qui nous occupe. Toutefois, mme avec XAML et peut-tre encore plus avec XAML, pensez larchitecture que vous allez implmenter dans votre programme avant de commencer la moindre lige de code.
Public Sub Charger(ByVal val As Short) If val = 1 Then m_nom = "Dupond" m_prenom = "Louis" m_adresse = "Rue des coteaux, 23" m_localite = "Pillion" m_cp = "23456" m_pays = 22 Else m_nom = "Durand" m_prenom = "Albert" m_adresse = "Rue des poteaux, 2" m_localite = "Paille" m_cp = "23765" m_pays = 24 End If End Sub End Class
Le but de cet exemple nest pas de vous apprendre travailler en couche. La classe mtier qui vous est prsente ici est trs simplie et la mthode de chargement des donnes nest l que pour permettre dafficher simplement un rsultat. Typiquement, nous devrions trouver dans la classe des mthodes de manipulation, de contrle, de transformation des donnes. Linteraction entre lobjet mtier et la couche daccs aux donnes nest pas gre par XAML. Il sagit de .NET pur. Le code .NET doit tre adapt pour charger lobjet mtier.
Partial Public Class Window1 Inherits Window
Le guide du codeur 205
En tout premier, nous devons dclarer notre objet mtier comme membre de la classe. Notez que nous avons galement conserv le DataSet. Il est encore ncessaire pour charger la liste des pays.
Private m_data As New DBXAMLDataSet Private m_business As New Business
Dans le constructeur, nous chargeons les donnes dans le DataSet et dans lobjet mtier.
Public Sub New() InitializeComponent() Dim adapter As New DBXAMLDataSetTableAdapters.PaysTableAdapter adapter.Fill(m_data.Pays) m_business.Charger(1) End Sub
Comme ctait le cas pour le DataSet, lobjet mtier est dclar comme champ de la classe. Il est initialis dans le constructeur et plac comme source de
206 Le guide du codeur
donnes dans la mthode Win_Load. Il manque bien videmment lenregistrement des donnes de lobjet mtier mais, l encore, il sagit de programmation .NET classique.
Rafrachissement An de provoquer le rafrachissement de lcran lorsque les valeurs sont recharges, la valeur Nothing est charge dans lattribut DataContext et est ensuite nouveau charge par m_business.
Selon les circonstances, vous pourriez avoir plusieurs objets mtier et changer le DataContext pour quil pointe sur lun ou lautre. Dans ce cas, typiquement, vous aurez une collection dobjets mtier.
Le chier XAML nest pas modi Les liaisons se font sur les noms des proprits de la classe. Comme nous avons donn les mmes noms nos proprits que les noms des champs dans le schma xsd, le code XAML peut rester tel que.
En dnitive, cet exemple dmontre quil est non seulement possible de lier nimporte quelle proprit une donne externe mais galement que la donne externe peut elle-mme tre conserve dans nimporte quelle classe dobjet.
<Record> <Nom>Durant</Nom> <Prenom>Louis</Prenom> <Titre>Directeur general</Titre> </Record> <Record> <Nom>Dupont</Nom> <Prenom>Leon</Prenom> <Titre>Product manager</Titre> </Record> <Record> <Nom>Durand</Nom> <Prenom>Carine</Prenom> <Titre>Directrice generale adjointe</Titre> </Record> </Records> </Table>
Ce chier contient donc une simulation de table dont le nom serait Direction et qui contient trois enregistrements. La structure de ce chier XML nest absolument pas une structure obligatoire et nest reprise qu titre dexemple. Une fois ce chier cr, nous pouvons maintenant raliser notre page XAML qui va lire directement ce chier. Les donnes seront affiches dans une ListView. Ce sera pour nous loccasion de dcouvrir ce contrle, qui se prte particulirement bien laffichage de donnes enregistres dans une source externe.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Grid> <Grid.Resources> <XmlDataProvider x:Key="data" Source=" Data.XML"/> </Grid.Resources> <Grid.DataContext> <Binding Source="{StaticResource data}" XPath="/Table/Records"/> </Grid.DataContext> <ListView Height="92" Margin="13,18,19,0" Name="MaListView" VerticalAlignment="Top" ItemsSource="{Binding XPath=Record/Nom}" </Grid> </Page>
b Figure 7-11 : Affichage du contenu dun chier XML dans une ListView
Comme vous pouvez le constater, la balise XmlDataProvider est extrmement simple dutilisation puisquil ne sagit que de donner un nom via lattribut x:Key et de dnir le chier en utilisant lattribut Source. Comme pour les techniques prcdentes, nous devons utiliser le DataContext. Cette fois, nous le faisons directement dans le chier XAML puisque la source est dnie en tant que ressource statique. Lattribut XPath va permettre de dterminer dans le chier XML le nud qui contient les donnes qui nous intressent. Il ne reste plus alors qu dnir la ListView. En dehors de lattribut ItemSource, qui permet de dnir les donnes associes, rien de bien neuf. Notez que, pour dnir les donnes, nous utilisons nouveau XPath. Le contenu du nud Nom inscrit dans chaque nud Record de la source de donnes (DataContext) servira dnir un lment de la liste. Si nous dsirons afficher plus dune information par liste, vous pouvez utiliser lattribut ItemTemplate de notre ListView. Pour cela, nous devons au pralable dnir un DataTemplate. Le DataTemplate sert dcrire le contenu et la faon de reprsenter chacun des lments de la liste. Il se place galement dans la zone des ressources.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Grid> <Grid.Resources> <XmlDataProvider x:Key="data" Source=" Data.XML"/>
<DataTemplate x:Key="DataListView"> <WrapPanel> <Label Content="{Binding XPath=Nom}"/> <Label Content="{Binding XPath=Prenom}"/> <Label Content="{Binding XPath=Titre}"/> </WrapPanel> </DataTemplate> </Grid.Resources> <Grid.DataContext> <Binding Source="{StaticResource data}" XPath="/Table/Records"/> </Grid.DataContext> <ListView Height="92" Margin="13,18,19,0" Name="MaListView" VerticalAlignment="Top" ItemsSource="{Binding XPath=Record}" ItemTemplate="{StaticResource DataListView}"/> </Grid> </Page>
Contenu dun DataTemplate Comme vous pouvez le remarquer, un DataTemplate peut contenir nimporte quel code XAML ou presque.
Un autre moyen dafficher plus dinformations est dutiliser un GridView. Le GridView est non pas proprement parler un autre contrle mais plutt une extension qui se place dans la proprit View de ListView. Il permet dafficher les informations dans des colonnes spares et mme de donner un titre ces colonnes. Si nous reprenons le mme exemple, nous devrons le modier comme suit.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Grid> <Grid.Resources> <XmlDataProvider x:Key="data" Source=" Data.XML"/> </Grid.Resources> <Grid.DataContext> <Binding Source="{StaticResource data}" XPath="/Table/Records"/> </Grid.DataContext> <ListView Height="92" Margin="13,18,19,0" Name="MaListView" VerticalAlignment="Top" ItemsSource="{Binding XPath=Record}"> <ListView.View>
Dans cet exemple, le GridView contient trois colonnes, une pour le nom, une pour le prnom et une pour le titre.
<GridView AllowsColumnReorder="True"> <GridViewColumn Header="Nom" Width="50" DisplayMemberBinding= "{Binding XPath=Nom}"/> <GridViewColumn Header="Prnom" Width="60" DisplayMemberBinding= "{Binding XPath=Prenom}"/> <GridViewColumn Header="Titre" Width="140" DisplayMemberBinding= "{Binding XPath=Titre}"/> </GridView> </ListView.View> </ListView> </Grid> </Page>
Dplacer les colonnes Pour permettre lutilisateur de dplacer les colonnes par glisser-dposer, vous devez assigner la valeur True lattribut AllowsColulmnReorder dans la balise GridView.
Si vous prfrez donner un aspect plus structur votre affichage, vous utiliserez probablement un TreeView. Sur la base du mme exemple, nous pouvons construire un petit TreeView mais, an de lui donner un aspect plus hirarchis, il y a lieu de modier au pralable notre source de donnes.
<Table> <Name> Direction </Name> <Records> <Administration> <Record> <Nom>Durant</Nom> <Prenom>Louis</Prenom> <Titre>Directeur general</Titre> </Record> <Record> <Nom>Durand</Nom> <Prenom>Carine</Prenom>
212 Le guide du codeur
<Titre>Directrice generale adjointe</Titre> </Record> </Administration> <Production> <Record> <Nom>Dupont</Nom> <Prenom>Leon</Prenom> <Titre>Product manager</Titre> </Record> </Production> </Records> </Table>
Avec les nuds Administration et Production, les membres de la direction sont maintenant groups selon leurs tches. Nous pouvons reprsenter cette structure dans le TreeView.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Grid> <Grid.Resources> <XmlDataProvider x:Key="data" Source="Data2.XML"/> <DataTemplate x:Key="Admin"> <WrapPanel> <Label Foreground="Blue" Content="{Binding XPath=Nom}"/> <Label Content="{Binding XPath=Prenom}"/> <Label Content="{Binding XPath=Titre}"/> </WrapPanel> </DataTemplate>
Nous pouvons dnir un deuxime DataTemplate sur la mme source. Dans lexemple, seule la couleur est modie, mais vous pourriez changer tous les lments.
<DataTemplate x:Key="Prod"> <WrapPanel> <Label Foreground="Green" Content="{Binding XPath=Nom}"/> <Label Content="{Binding XPath=Prenom}"/> <Label Content="{Binding XPath=Titre}"/> </WrapPanel> </DataTemplate> </Grid.Resources> <Grid.DataContext>
Le guide du codeur 213
<Binding Source="{StaticResource data}" XPath="/Table/Records"/> </Grid.DataContext> <TreeView Margin="13,18,19,0" Name="MaTreeView" Background="Azure"> <TreeViewItem ItemsSource="{Binding XPath=Administration/Record}" Header="Administration" ItemTemplate="{StaticResource Admin}"/> <TreeViewItem ItemsSource="{Binding XPath=Production/Record}" Header="Production" ItemTemplate="{StaticResource Prod}"/> </TreeView> </Grid> </Page>
Comme vous pouvez le constater, chaque lment du TreeView possde sa propre source ou plutt son propre chemin vers les donnes. Il peut aussi avoir sa propre reprsentation mais, gnralement, le modle (DataTemplate) sera le mme pour lensemble des lments. Voyons maintenant comment raliser une liaison avec un objet en utilisant
ObjectDataProvider.
Nous devons tout dabord crer une classe. Prenons comme exemple la classe Auteur, qui contient son nom et une collection de livres quil a crits.
Ensuite, nous avons besoin dune collection type pour stocker les objets Livre.
Public Class Livres Inherits ObservableCollection(Of Livre) Public Sub New() End Sub End Class
Maintenant, nous pouvons passer au code XAML et lutilisation dObjectDataProvider. La proprit ObjectType va nous permettre de spcier le type dobjet qui sera cr.
Le paramtre ConstructorParameters, que nous nutiliserons pas ici, permet de transmettre des paramtres au constructeur. Les autres techniques utilises ont dj t vues prcdemment.
<Window xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:ObjectProviderExemple" > <Window.Resources> <ObjectDataProvider x:Key="sk" ObjectType="{x:Type src:Auteur}"/> <DataTemplate x:Key="NomAuteur"> <TextBlock Text="{Binding Path=Name}" /> </DataTemplate> </Window.Resources> <StackPanel DataContext= "{Binding Source={StaticResource sk}}" Margin="10,10,10,0"> <TextBlock Text="{Binding Path=Name}" Background="LightGray" /> <ListView Background="LemonChiffon" ItemsSource="{Binding Path=Livres}" ItemTemplate="{DynamicResource NomAuteur}" /> </StackPanel> </Window>
ObjectProviderExemple
Les paramtres ObjectInstance, MethodName et MethodParameters tendent encore les possibilits de cette classe en permettant entre autres laccs des mthodes de lobjet cr.
Le guide du codeur 217
7.4 Checklist
Dans ce chapitre sur la connexion aux donnes, nous avons essentiellement vu :
j
j j j
j j
comment lier un objet DataSet ou autre avec un contrle en utilisant les proprits DataContext et Source ; comment lier les donnes en utilisant Binding ; comment lier les donnes un chier XML en utilisant XmlDataProvider ; comment afficher les donnes dans une ListView ou de manire plus labore avec un GridView ; comment afficher les donnes dans une arborescence avec TreeView ; comment lier les donnes un objet en utilisant ObjectDataProvider.
Ch apit re
8 Fonctionnalits avances
Appliquer des transformations sur les contrles ....................................... Crer une ressource .................................. Crer un style ........................................... Checklist ..................................................
Fonctionnalits avances
<Label Name="lblPremierLabel" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Verdana" FontSize="14" FontWeight="Heavy" FontStyle="Italic" FontStretch="UltraExpanded" Foreground="Aquamarine" Background="Blue"> Mon premier label. <Label.RenderTransform> <RotateTransform Angle="270" /> </Label.RenderTransform> </Label>
Accder une proprit grce un nud ls Pour la premire fois, nous utilisons une proprit de la classe non pas en la dnissant grce un attribut mais bien comme un nud ls de notre nud Label.
Notez la prsence de lattribut CenterY, qui comme CenterX permet de modier la position du contrle en mme temps que lui est applique la transformation.
Fonctionnalits avances
Si vous ne trouvez pas votre bonheur dans ces transformations, vous pouvez toujours utiliser une transformation grce une matrice.
<Label Name="lblPremierLabel" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Verdana" FontSize="14" FontWeight="Heavy" FontStyle="Italic" FontStretch="UltraExpanded" Foreground="Aquamarine" Background="Blue" RenderTransform= "1,-0.5,0,1,0,0"> Mon premier label. </Label>
Nous revenons avec cette commande dans la structure plus traditionnelle dun attribut de notre balise. Chaque chiffre de la matrice applique une transformation notre label.
Les transformations appliques prcdemment sur un Label peuvent parfaitement tre utilises avec dautres contrles. Par exemple, leffet sur un texte long est, pour qui a lhabitude des limites de lAPI Win32, toujours trs surprenant.
<TextBlock Name="blckTexte" MaxWidth="200" MaxHeight="70" TextWrapping="Wrap" TextTrimming="WordEllipsis" Margin="5,5,5,5" TextAlignment="Justify" > Nous sommes maintenant arrivs notre deuxime contrle. Comme vous avez dj pu le constater, XAML est la fois simple dutilisation et performant. <TextBlock.RenderTransform> <RotateTransform CenterX="100" CenterY="100" Angle="270"/> </TextBlock.RenderTransform> </TextBlock>
Fonctionnalits avances
pouvoir rutiliser le code sans devoir le rcrire compltement. Ce qui permet un gain de temps mais aussi limite les risques de bug ou doubli en cas de modication. Prenons un exemple simple de ressource.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Page.Resources> <SolidColorBrush Color="Gold" x:Key="Background1"/> <SolidColorBrush Color="Lavender" x:Key="Background2"/> </Page.Resources> <StackPanel> <TextBox Background="{StaticResource Background1}"/> <TextBox Background="{StaticResource Background2}"/> <TextBox Background="{StaticResource Background1}"/> <TextBox Background="{StaticResource Background1}"/> <TextBox Background="{StaticResource Background2}"/> </StackPanel> </Page>
Le nom de la ressource est dni grce lattribut x :key. La ressource est accde en assignat {StaticResource NomDeLaRessource} lattribut cible. Si vous changez la ressource, toute la page est directement affecte. Il nest pas ncessaire de modier chaque contrle.
Nous avons utilis les ressources de manire statique, il est toutefois possible de les utiliser de manire dynamique en remplaant le mot cl StaticResource par DynamicResource. Cette possibilit nest intressante que quand la ressource peut tre modie. Elle pourra alors tre recharge. Il est possible davoir deux ressources portant le mme nom pour autant quelles ne soient pas dnies dans la mme balise. Pour retrouver une ressource, XAML remonte niveau aprs niveau la recherche de cette ressource. Pour la lisibilit du code, il est malgr tout fortement conseill dutiliser des noms diffrents.
<Page xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Page.Resources> <SolidColorBrush Color="Red" x:Key="Background1"/> <SolidColorBrush Color="Blue" x:Key="Background2"/> </Page.Resources> <StackPanel> <StackPanel.Resources> <SolidColorBrush Color="Lavender" x:Key="Background1"/> </StackPanel.Resources>
Fonctionnalits avances
<TextBox Background="{StaticResource <TextBox Background="{StaticResource <TextBox Background="{StaticResource <TextBox Background="{StaticResource <TextBox Background="{StaticResource </StackPanel> </Page>
Les ressources sont aussi un moyen simple pour partager un menu contextuel entre plusieurs lments.
<Window.Resources> <ContextMenu x:Key="CtxtMnu"> <MenuItem Header="Copier"/> <MenuItem Header="Coller"/> </ContextMenu> </Window.Resources> <TextBox Name="txtNom" Canvas.Top="10" Canvas.Left="80" Width="150" MaxLength="30" CharacterCasing="Upper" Text ="{Binding Path=Nom}" ContextMenu="{StaticResource CtxtMnu}" /> <Label Name="lblPrenom" Canvas.Top="10" Canvas.Left="240"> Prnom </Label> <TextBox Name="txtPrenom" Canvas.Top="10" Canvas.Left="300" Width="130" MaxLength="30" Text ="{Binding Path=Prenom}" ContextMenu="{StaticResource CtxtMnu}"/>
226 Le guide du codeur
Crer un style
Si nous analysons ce code, la premire chose faire est de donner un nom ce style avec lattribut x:Key. La balise Setter va nous permettre de dnir la proprit affecte. Il ne nous reste