0% ont trouvé ce document utile (0 vote)
451 vues61 pages

Windows Presentation Foundation

Transféré par

Ahlam Malak
Copyright
© Attribution Non-Commercial (BY-NC)
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
451 vues61 pages

Windows Presentation Foundation

Transféré par

Ahlam Malak
Copyright
© Attribution Non-Commercial (BY-NC)
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Windows Presentation Foundation :

La nouvelle génération d’interfaces graphiques

Windows Presentation Foundation :


La nouvelle génération d’interfaces graphiques

Avec l’arrivé de Windows VISTA, on assiste à l’apparition des nouvelles technologies qui
lui sont liées. Que ce soit au niveau affichage (avec Windows Presentation Foundation) ou
bien communication (avec Windows Communication Foundation), en passant par le
système de fichier (Windows File System, WinFS), beaucoup de choses changent.

Cet article a pour but de vous parler de Windows Presentation Foundation, le système
graphique qui sera inclut dans Windows VISTA.

Thomas LEBRUN
[Link] 1
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

1. Windows Presentation Foundation : Qu’est-ce-que


c’est ?
Windows Presentation Foundation (WPF), anciennement connu sous le nom de code
Avalon, est le nouveau système d’affichage graphique de Microsoft Windows, et devrait être
intégré directement dans Microsoft Windows VISTA.

WPF fait partie de WinFX, un nouvel ensemble d’API entièrement managées qui seront
introduites dans Microsoft Windows VISTA pour remplacer les API Windows actuelles.

Voici une image qui vous permettra, je l’espère, de bien comprendre l’architecture de WPF :

WPF repose sur 4 grands axes :


1. Une approche unifiée de l’interface utilisateur, des documents et des animations :
WPF a pour but de devenir un Framework de présentation unifié, qui intègre et
gère toutes les parties d’une interface utilisateur (animations, images, contrôles,
etc..).
2. Un moteur de composition basé sur des vecteurs intégrés :
WPF utilise un moteur d’exécution (Runtime) de composition afin d’expédier les
requêtes de rendu de l’interface graphique au bon composant logiciel ou matériel,
par exemple les APIs Windows ou votre carte vidéo compatible DirectX. WPF
utilise donc toute la puissance de votre ordinateur, au travers de votre carte
graphique, et plus précisément de Direct3D, pour vous fournir un affichage
vectoriel.

Thomas LEBRUN
[Link] 2
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

3. Un modèle de programmation déclarative :


WPF tente de réduire l’écart qu’il existe entre le développement Web et le
développement d’applications Windows, en apportant la puissance de la
programmation déclarative (le XAML) au développement d’interfaces graphiques
Windows, ce qui mène à une séparation distincte entre le rôle du designer et celui
du développeur. Les designers sont donc directement impliqués dans le
développement des applications.

4. Une facilité de déploiement :


WPF permet aux administrateurs de déployer et gérer les applications de manières
sécurisées.

Concrètement, Windows Presentation Foundation vous permettra de développer des


applications intuitives au design innovant.

Thomas LEBRUN
[Link] 3
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

2. Les pré-requis
Pour pouvoir utiliser une application WinFX, il ne vous faut rien de plus que le Runtime
WinFX.
La CTP de Février 2006 de ce Runtime est disponible à cette adresse :
[Link]
172BFA3B828B&displaylang=en

Si vous souhaitez pouvoir développer des applications WinFX, il va vous falloir plusieurs
choses :
1. Tout d’abord, il vous faut le Runtime WinFX. Là encore, la version de Février 2006
est disponible :
[Link]
474F-86D3-172BFA3B828B&displaylang=en
2. Un outil de développement : même si vous pouvez tout faire à la main, et compiler en
ligne de commande, je vous recommande vivement d’utiliser un IDE (Integrated
Development Environment ou Environnement de Développement intégré, en français)
qui vous permettra de bénéficier des fonctionnalités comme le glisser/déposer de
composants, etc….Pour cela, je vous recommande Visual Studio 2005.
A noter que les versions Express de Visual Studio sont disponibles ici :
[Link] Pour rappel, les versions
Express sont des versions de Visual Studio qui sont limitées à un seul langage qui
possèdent des fonctionnalités réduites mais largement suffisantes.
3. A présent, il vous faut télécharger et installer le SDK de Windows. Celui-ci contient
des API qui vous seront nécessaires pour vos développements, ainsi que de la
documentation, des exemples et des outils. La version de Février 2006 du SDK de
Windows peut-être téléchargée ici :
[Link]
88DD-61E3EF88C402&displaylang=en
4. Une des choses dont vous aurez probablement besoin (mais cela n’est pas obligatoire),
est un ensemble d’outils de développement pour WinFX. Ces outils sont, par exemple,
des Template de projet pour Visual Studio, l’intellisense XAML dans Visual Studio,
etc… A noter qu’un des outils présents dans ce package n’est autre que Cider, le
designer d’interface graphique de WPF ! (On notera que même si le produit est
toujours en développement, on peut tout à fait commencer à l’utiliser pour se faire une
idée de ce qu’il donnera une fois terminé). Pour télécharger et installer ces outils de
développement (ou tout du moins la version de Février 2006), rendez-vous à cette
adresse : [Link]
D7B6-44BC-910D-E91F3E370477&displaylang=en
5. Enfin, si vous travaillez avec Windows Worflow Foundation (un ensemble constitué
d’un modèle de programmation, d’un moteur de workflow et d’outils pour développer
rapidement des applications de workflow sur Windows), alors vous voudrez sans
doute installer, en plus, les extensions de Visual Studio 2005 pour Windows
Workflow Foundation. La version de Février 2006 de ce package est téléchargeable à
sur le site de Microsoft :
[Link]
A707-5883FF4C1DC2&displaylang=en

Thomas LEBRUN
[Link] 4
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

3. Les outils pour développer des applications WPF


a. Le XAML :
Le XAML (eXtensible Application Markup Language) est un modèle de programmation
déclarative .NET.
C’est donc un langage basé sur le XML (eXtensible Markup Language), qui fonctionne sur le
principe de la sérialisation de graphe d’objets.

Comme beaucoup de langage .Net, on y retrouve donc :


• Des espaces de nom (namespaces en anglais),
• Des classes,
• Des propriétés,
• Un mapping des évènements (Appel dans le code XAML et définition dans le code
C#, [Link], etc…),
• Etc…

Une chose importante à savoir : XAML est un langage de description qui n’est pas dédié à
WPF !

Pour vous permettre de mieux visualiser ce qu’est le XAML, voici un bout de code :

<Window x:Class="DemosWPF.Window1"
xmlns=[Link]
xmlns:x=[Link]
Title="DemosWPF" Height="768" Width="1024"
WindowStartupLocation="CenterScreen"
>

Dans cet exemple, on voit bien la déclaration des espaces de nom

xmlns:x=[Link]

Ainsi que la déclaration de la classe :

x:Class="DemosWPF.Window1"

Quant aux propriétés, elles correspondent tout simplement aux attributs des éléments du code
XAML. Par exemple, l’attribut Title de l’élément Window correspond tout simplement à la
propriété Title de la classe Window.

Title="DemosWPF"

Thomas LEBRUN
[Link] 5
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Il est également bon de savoir que tout ce que vous développez avec du code XAML peut-
être redéveloppé avec du code, comme le montre cette image :

b. Cider :
Cider est le nom de code du designer d’interface graphique de WPF. Celui-ci, toujours en
version Beta, sera inclu dans Orcas (nom de code de la prochaine version de Visual Studio).

Comme la plupart des designers d’interface graphique, Cider offre la possibilité d’utiliser le
glisser/déposer (Drag&Drop) pour placer vos composants (boutons, labels, listbox, etc….)
au sein de votre formulaires.

Voici quelques captures d’écran de Cider (à ce jour) et des différents contrôles qui sont
d’ores et déjà pris en charge :

La fenêtre principale :

Thomas LEBRUN
[Link] 6
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

La fenêtre des contrôles utilisables : La fenêtre de Propriétés :

Cider apparaît donc comme un outil à la fois simple et très puissant, qui vous permet de
développer, rapidement, des interfaces graphiques complexes.

c. La gamme Expression :
Nous l’avons vu précédemment, un des objectifs de WPF est de permettre une meilleure
collaboration entre les designers et les développeurs.

Pour cela, Microsoft a sortit une nouvelle gamme de produits : la gamme Expression.
Cette gamme est composée de trois logiciels destinés, principalement, aux designers et aux
graphistes :

- Expression Graphic Designer (nom de code : Acrylic) :


C’est un logiciel axé plus particulièrement sur le
traitement d’images vectorielles ou bitmap.

Thomas LEBRUN
[Link] 7
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

- Expression Interactive Designer (nom de code :


Sparkle) : Il vous permettra de créer des applications
simples, innovantes et esthétiques, avec une pointe
d’interactivité.

- Expression Web Designer (nom de code : Quartz) :


Grâce à cet outil, vous serez en mesure de créer et
développer des sites Web basés sur les standards.

Voici d’ailleurs plusieurs aperçus de Sparkle :

La fenêtre principale :

Thomas LEBRUN
[Link] 8
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Une partie de l’espace de travail : Une autre partie de l’espace de travail :

Et un aperçu de la fenêtre principale (vue du code) :

Pour plus d’informations, visitez le site Web de la gamme Expression :


[Link]

Thomas LEBRUN
[Link] 9
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

4. Développer des applications WPF


a. Les contrôles WPF :
De manière générale, les contrôles sont utilisés pour visualiser des données et pour permettre
à l’utilisateur d’interagir avec l’application.

Comme souvent, les contrôles WPF possèdent des propriétés, des évènements et des
méthodes.
On retrouve beaucoup de contrôles standards dans WPF : les boutons, les labels, les textbox,
etc…

Bien sur, la grande nouveauté des contrôles WPF est qu’ils peuvent contenir n’importe quoi :
on a donc la possibilité de personnalisé complètement le rendu d’un contrôle WPF.
En effet, ce sont des éléments fonctionnels auquels on applique un style et qu’il est possible
de combiner avec d’autres grâce au système de template.

Par exemple, le bout de code suivant permet d’insérer simplement une image dans un bouton :

<Button Name="m_BoutonMirroir" VerticalAlignment="Top"


HorizontalAlignment="Center" Width="200" Height="100">
<Image Source="{Binding Source=Images/[Link]}" />
</Button>

Voici une image montrant le résultat de ce bout de code :

On a réussi à personnaliser un bouton de façon très simple et avec très peu de lignes de code ;
ce qui nous aurait pris beaucoup plus de temps si nous avions du faire la même chose en C#
ou en [Link], dans une application WindowsForms classique.

Afin de bien comprendre comment fonctionnent les contrôles WPF, je vous recommande de
regarder cette image (extraite des slides de la PDC 2005) :

Thomas LEBRUN
[Link] 10
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Ici, vous avez une description complète de l’architecture des contrôles, dans Windows
Presentation Foundation.

Voyons cela plus en détails :


L’affichage, sous WPF, est donc géré par deux threads : le premier s’occupe de créer les
éléments primitifs qui vont servir à l’affichage, tandis que le deuxième se charge de les
afficher à l’écran. Le premier thread est entièrement managé et le deuxième est natif !
On voit donc que tous les contrôles WPF sont en fait constitués d’autres contrôles. Par
exemple, une ListBox n’est qu’un StackPanel accompagné d’un SrollViewer.

On peut donc décomposer chaque contrôle WPF sous forme de graphes d’objets, jusqu'à
obtenir un ensemble de données qui seront affichées à l’écran.

La propriété Content des contrôles WPF remplace la propriété Text des contrôles
« classiques », mais vous permet bien plus. En effet, c’est grâce à cette propriété Content, qui
est mappée sur les enfants d’un nœud XAML, que vous allez pouvoir faire « ce que vous
voulez » avec votre contrôle : ajouter une image, une vidéo, etc….
Vous allez même pouvoir aller plus loin. En effet, si vous étudiez bien cette propriété, vous
vous rendrez compte qu’elle est de type object. Ainsi, vous avez la possibilité de lui assigner
n’importe quel objet (objet métier, etc..).

b. Les ressources
Chaque composant WPF possède une propriété Resources qui, comme son nom l’indique,
permet de définir les ressources qui lui seront associées.
Par ressources, on entend beaucoup de choses :
o les styles (définissent l’apparence d’un contrôle),
o les templates (permettent de définir comment afficher les données affectées à
un contrôle),
o les animations
o les transformations (rotation, etc…)

Ces ressources vous permettent d’avoir accès et donc de réutiliser des objets définis pour
l’ensemble de votre application
Voici un exemple dans lequel on définit, dans les ressources d’une Grid, le style qui sera
appliqué à des contrôles de type Button. Si vous ne comprenez pas ce code, ne vous inquiétez
pas : nous y reviendrons plus en détails juste après, dans la partie traitant des Styles.

<Grid>
<!—
Dans les ressources de la grille
-->
<[Link]>
<!—
On definit un style, qui sera appliqué au type définit
On définit la propriété à modifier et la valeur à lui appliquer
-->

<!—

Thomas LEBRUN
[Link] 11
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

On modifie le style, la couleur, etc.. de la police


-->
<Style TargetType="{x:Type Button}" x:Key="MonStyleDePolice">
<Setter Property="[Link]" Value="Italic" />
<Setter Property="[Link]" Value="Bold" />
<Setter Property="[Link]" Value="Red" />
</Style>
</[Link]>
</Grid >

Ainsi, on se rend compte que les ressources de nos contrôles peuvent facilement être
assimilées aux fichiers CSS des applications Web : bien que toujours interne à notre
application, on « externalise » tout ce qui concerne le design/l’apparence pour se concentrer
uniquement sur les fonctionnalités.
Il n’est plus nécessaire de spécifier, pour chaque type de contrôle, le style ou le template à
appliquer : en passant par les ressources, vous pouvez définir un style (ou un template)
spécifique à chaque type de contrôle, et l’appliquer lors de la déclaration de ceux-ci.

c. Les styles
Nous l’avons vu précédemment : les styles permettent de définir l’apparence de vos contrôles.
Nous avons également vu comment définir un style :
Au moyen de l’élément Style, on indique que l’on veut définir un style.
Ensuite, c’est très simple : il ne nous reste plus qu’à utiliser des Setter, qui vont nous servir à
définir la propriété à modifier (grâce à la propriété Property) et la valeur à lui attribuer
(propriété Value).

Et voilà, à partir de ce moment là, il ne vous reste plus qu’à attribuer, à un de vos contrôles, le
style que vous venez de définir. Pour cela, il vous faut juste « lier » la propriété Style de votre
contrôle au style que vous venez de créer.

<TextBlock Text="Un bouton avec une police personnalisée" />


<Button Style="{StaticResource MonStyleDePolice}" Content="Bouton
avec Police Personnalisée" />

Notez bien que pour trouver à quel style on veut se lier, nous devons :
o utiliser l’attribut Key de notre style
o utiliser l’attribut TargetType, qui nous permet d’indiquer pour quel type de
contrôle ce style sera valable.

Voyons voir ce que cela donne, en image :

L’exemple ici n’est pas des plus pertinents, mais il a l’avantage de vous permettre de bien
vous rendre compte du rendu de l’application du style à notre bouton.

Thomas LEBRUN
[Link] 12
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Autre point important : Vous avez la possibilité de créer un style à partir d’un autre style, ce
qui a l’énorme avantage de vous permettre de ne pas refaire plusieurs fois le même travail et
de pouvoir partir sur une base déjà existante.

Pour cela, il vous faudra utiliser l’attribut BasedOn, lors de la déclaration de votre style, et lui
indiquer le style sur lequel vous souhaitez vous baser.

Voyons un exemple :

<!—
Style basé sur un autre
-->
<Style TargetType="{x:Type Button}" x:Key="MonStyleHerite"
BasedOn="{StaticResource MonStyleDePolice}">
<Setter Property="[Link]" Value="Green" />
</Style>

Dans cet extrait de code, on voit bien que l’on redéfinit un style, qui porte la « clé »
MonStyleHerite, et qui se base sur notre style précédemment définit, MonStyleDePolice.

Le code qui utilise ce style, tout ce qu’il y a de simple :

<TextBlock Text="Un bouton avec un style hérité" />


<Button Style="{StaticResource MonStyleHerite}" Content="Bouton Perso
avec Style Hérité" />

Là encore, le résultat est rapidement visible, la preuve en image :

On peut donc affirmer que les styles, dans WPF, s’avèrent très utiles et très puissants et
permettent de réaliser des applications dont vous pouvez entièrement modifier le
design/l’apparence.

d. Les templates
Les Templates sont utilisés pour décrire la structure visuelle d’un contrôle. Pour cela, les
contrôles WPF présentent la propriété Template, qui vous permettra donc d’associer un
template, que vous avez définit, à un contrôle.

Pour appliquer un template, la syntaxe est la même que pour appliquer un style :

<TextBlock Text="Un bouton avec un template personnalisé" />


<Button Template="{StaticResource MonTemplateDeBouton}"

Thomas LEBRUN
[Link] 13
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Et voici le template qui lui est associé :

<ControlTemplate TargetType="{x:Type Button}"


x:Key="MonTemplateDeBouton">
<Grid>
<Ellipse Width="135" Height="65">
<[Link]>
<SolidColorBrush Color="Black" />
</[Link]>
</Ellipse>
<ContentPresenter />
</Grid>
</ControlTemplate>

Comme vous pouvez le voir, on utilise un élément de type ControlTemplate pour définir le
template, autrement dit la façon dont notre contrôle sera affiché : simple non ? ☺

Voici, pour vous donner un aperçu, le résultat de ce template :

Nous aurions également pu passer par un style pour définir la propriété Template de notre
contrôle :

<Style TargetType="{x:Type Button}">


<Setter Property="Template" />
<[Link]>
<ControlTemplate TargetType="{x:Type Button}"
x:Key="MonTemplateDeBouton">
<Grid>
<Ellipse Width="135" Height="65">
<[Link]>
<SolidColorBrush Color="Black" />
</[Link]>
</Ellipse>
<ContentPresenter />
</Grid>
</ControlTemplate>
</[Link]>
</Style>

Je vous épargne la capture d’écran, étant donné qu’elle donne le même résultat que la capture
précédente ;)

Les DataTemplates sont utilisées pour définir une représentation visuelle d’un objet de
données. On peut donc dire que les DataTemplates permettent à une application d’afficher à
l’écran des objets non-visuels, autrement dit des objets de données.

Thomas LEBRUN
[Link] 14
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Voyons cela en exemple :

Prenons la classe MyPhoto :

class MyPhoto
{
private int m_IdPhoto;

public int IdPhoto


{
get { return m_IdPhoto; }
set { m_IdPhoto = value; }
}

private string m_SourcePhoto;

public string SourcePhoto


{
get { return m_SourcePhoto; }
set { m_SourcePhoto = value; }
}
}

Comme vous pouvez le constatez, cette classe ne comporte aucun élément visuel. Nous allons
donc utiliser un DataTemplate pour définir la façon dont les éléments de type MyPhoto
devront être affichés :

<DataTemplate DataType="{x:Type m:MyPhoto}">


<Image Source="{Binding Filename}" />
</DataTemplate>

Ainsi, nous définissons le fait que tous les éléments de types MyPhoto doivent être affichés
sous forme d’une image, qui aura sa source « bindée » (liée) à la propriété Filename de notre
source de données.
La conséquence de ceci est simple : dès qu’un objet de type MyPhoto sera détecté dans votre
application, c’est ce template qui sera appliqué à cet objet.

Attention tout de même : Pour pouvoir réaliser à bien cette opération, il nous a fallut mapper
le type MyPhoto au XAML, au moyen de l’attribut xmlns :

<Window x:Class="DemosWPF.Window1"
xmlns:x="[Link]
xmlns=[Link]
Title="DemosWPF" Height="768" Width="1024"
xmlns:m="clr-namespace:DemosWPF"
>

e. Les triggers
Les Triggers sont utilisés conjointement avec les styles et les templates, afin de réaliser des
applications proposant des interactions riches et dynamiques.

Thomas LEBRUN
[Link] 15
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Voici la règle qui vous permet de comprendre les Triggers :

Les Triggers sont activés lorsqu’une condition spécifique devient vraie.

Il faut également savoir que WPF vous permet de vérifier trois choses dans les conditions
d’un trigger :
o une « Property Dependency » (utilisation de Trigger)
o une propriété .NET (utilisation de DataTrigger)
o un événement (utilisation d’EventTrigger)

Dans le cas des deux premières conditions, le trigger est déclenché lorsque la propriété
spécifiée est modifiée.
Dans le dernier cas, le trigger est déclenchée lorsque l’évènement indiqué survient (par
exemple, le clic sur un bouton)

Pour modifier la valeur d’une propriété, dans un trigger, vous devez là encore utiliser
l’élément Setter :

<!—
On utilise un Trigger sur ce style pour faire en sorte de
changer la couleur du fond lorsque la
souris est sur le bouton
-->
<[Link]>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="[Link]" Value="Red" />
</Trigger>
</[Link]>

Dans cet exemple, nous ajoutons un Trigger qui sera déclenché lorsque la propriété
IsMouseOver passera à vrai. Dans ce cas, on change la propriété Background de notre
bouton, pour la faire passer à rouge.

Bien entendu, vous avez la possibilité d’utiliser plusieurs Triggers dans un style, ceci afin de
permettre la modification de multiples propriétés lors du changement des valeurs de
différentes propriétés :

<!—
On utilise un Trigger sur ce style pour faire en sorte de
changer la couleur du fond lorsque la
souris est sur le bouton
-->
<[Link]>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="[Link]" Value="Red" />
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="[Link]" Value="Green" />
</Trigger>
</[Link]>

Thomas LEBRUN
[Link] 16
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Vous pouvez également ajouter des triggers qui ne s’exécuteront que sous certaines
conditions. Pour cela, vous devez utiliser un MultiTrigger, dans lequel vous spécifier, dans
l’élément Conditions, les différentes conditions qui doivent être remplies pour que votre
trigger s’exécute :

<MultiTrigger>
<[Link]>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsFocused" Value="True" />
</[Link]>

<Setter Property="[Link]" Value="Black" />


</MultiTrigger>

Dans cet exemple, on s’assure que les propriétés IsMouseOver et IsFocused sont bien à
vrais. Si ces deux conditions sont bien remplies, alors on change la propriété Foreground de
notre bouton.

Prenez garde à ne pas oublier que ces types de triggers ne s’exécutent que si toutes les
conditions sont vérifiées : dans le cas contraire, le trigger ne fonctionnera pas.

Après avoir vu les triggers de propriétés, attardons nous un instant sur les triggers de données
(DataTriggers) pour voir à quel point ils peuvent s’avérer pratiques.
En effet, si les triggers de propriétés ne peuvent effectuer de vérifications que sur les
« Property Dependencies », les DataTriggers ont la possibilité de pouvoir effectuer des
vérifications sur n’importe quelle propriété d’un objet .NET.

Tout comme les DataTemplate, les DataTriggers sont utilisés avec les objets « non visuels » :
ils peuvent donc vérifier les propriétés de n’importe quel objet .NET « non visuel ».

Reprenons notre classe MyPhoto et imaginons, par exemple, que l’on souhaite effectuer une
action lorsque l’identifiant d’une photo est égal à une valeur donnée. Dans ce cas, on ne peut
pas utiliser de Trigger simple, pour la simple et bonne raison que MyPhoto n’est pas un objet
que l’on peut représenter visuellement : la propriété IdPhoto (qui sert à connaitre l’identifiant)
est donc une propriété qui, elle aussi, ne peut être définie visuellement. Par conséquent, si l’on
souhaite faire une vérification sur une propriété de ce type, il nous faut utiliser un
DataTrigger.

Cette notion pouvant paraitre compliquée, voici un exemple qui vous aidera, je l’espère, à
mieux comprendre de quoi il s’agit :

<DataTrigger Binding="{Binding Path=IdPhoto}" Value="1">


<Setter Property="[Link]" Value="Yellow" />
</DataTrigger>

Dans cet exemple de DataTrigger, on fait un test sur la propriété IdPhoto de notre source de
données. On teste, en effet, si la valeur de cette propriété est égale à un. Dans ce cas, on fait
changer la couleur du texte de notre bouton.

On voit tout de suite que, si les triggers de propriétés agissent sur le style, l’apparence des
objets, les triggers de données eux agissent sur le contenu des objets.

Thomas LEBRUN
[Link] 17
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Le dernier point qu’il nous reste à voir à propos des triggers concerne les EventTriggers,
autrement dit les triggers qui sont déclenchés suite à un événement.
En effet, dès qu’un événement survient, tel que l’événement Click d’un bouton, un
EventTrigger est déclenché en réponse à cet événement.

Pour bien comprendre cela, voyons un exemple simple :

<Button Name="m_BoutonRotation" VerticalAlignment="Top"


Margin="0,20,812,0" Content="Rotation" Width="75" Height="23">
<[Link]>
<!—
Lors du clic sur le bouton
-->
<EventTrigger RoutedEvent="[Link]">
<[Link]>

</[Link]>
</EventTrigger>
</[Link]>
</ Button >

Que se passe-t-il dans ce bout de code ?


La réponse est simple : on commence par déclarer un bouton, de manière déclarative (c’est-à-
dire avec du code XAML), puis on définit certaines de ses propriétés.
Ensuite, on ajoute à la collection de Triggers de ce bouton, un nouveau trigger, qui surviendra
lors de l’événement [Link], autrement dit lors du clic sur le bouton.
Dans ce trigger, on définit ce qu’il va se passer (autrement dit, on indique la ou les actions à
effectuer), au moyen de l’élément Actions de notre trigger.

Nous allons à présent voir un autre élément important dans l’utilisation des EventTriggers,
les StoryBoards.

f. Les storyboards
Les StoryBoards sont des éléments XAML qui vous permettent de définir un ensemble
d’actions.
On peut donc dire que les Storyboards sont un ensemble d’animations/transformations, qui
vous offre la possibilité de pouvoir définir le temps que doivent durer vos animations, la
propriété à modifier sur votre objet, etc….

Bref, les StoryBoards vous permettent un paramétrage complet de vos animations.

Thomas LEBRUN
[Link] 18
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Attardons nous maintenant sur deux propriétés intéressantes de l’élément StoryBoard :

• La propriété TargetName :
Cette propriété est utilisée pour définir la cible, autrement dit l’objet,
que l’on désire manipuler. Il peut s’agir d’un élément, d’une rotation,
etc…

• La propriété TargetProperty
Cette propriété, quand à elle, est utilisée pour indiquer, sur notre
cible, quelle est la propriété que l’on souhaite manipuler : un angle,
une taille, etc….

Afin de bien comprendre ces deux propriétés, voici un exemple :

<Button Name="m_BoutonRotation" VerticalAlignment="Top"


Margin="0,20,812,0" Content="Rotation" Width="75" Height="23">
<[Link]>
<!—
Lors du clic sur le bouton
-->
<EventTrigger RoutedEvent="[Link]">
<[Link]>
<BeginStoryboard>
<!—
On ajoute un storyboard qui visera
MyObject et plus particulièrement la propriété MyProperty
-->
<Storyboard
[Link]="MyObject"
[Link]="MyProperty">
</Storyboard>
</BeginStoryboard>
</[Link]>
</EventTrigger>
</[Link]>
</ Button >

On a donc repris le code utilisé précédemment, mais nous y avons ajouté plusieurs éléments :
• un élément BeginStoryboard, utilisé pour démarrer un Storyboard
• un élément Storyboard, qui servira à indiquer que l’on souhaite
déclarer un nouveau Storyboard

Dans la déclaration de notre élément Storyboard, nous avons utilisé les deux propriétés vues
juste avant, afin d’indiquer avec quel objet nous désirons travailler, et plus précisément quelle
propriété de cet objet nous allons modifier lors de l’exécution de notre Storyboard.

Bien entendu, l’élément Storyboard possède d’autres propriétés intéressantes, que nous allons
voir tout de suite :

o AutoReverse : Indique si, une fois arrivé à la fin du StoryBoard, l’animation


doit revenir à sa position initiale,
o BeginTime : Indique à quel moment le StoryBoard doit démarrer,
o Duration : Vous permet de spécifier combien de temps doit durer votre
animation
Thomas LEBRUN
[Link] 19
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Bien sûr, il existe d’autres propriétés mais le but de cet article n’est pas de vous en faire la
liste.

Maintenant que nous avons vu à quoi servent les StoryBoards, nous allons voir quels sont les
éléments qu’il est commun d’utiliser afin d’animer vos boutons, TextBox, etc…
Vous pouvez utiliser, pour cela, des animations et des transformations, que nous allons voir
un peu plus en détails maintenant.

g. Les animations
Dans vos applications WPF, vous avez la possibilité d’utiliser des animations, qui vous
permettront d’animer vos contrôles.
Par exemple, vous allez pouvoir faire en sorte que pendant 10 secondes, la taille d’un bouton
augmente, etc….
Bref, les possibilité offertes par les animations WPF sont énormes, et ne doivent pas être
négligées si vous voulez réaliser des applications au design et à l’interaction utilisateur
innovante !

Pour manipuler un élément, et plus précisément la propriété d’un élément, vous devez utiliser
les deux propriétés que nous avons vues précédemment : TargetName et TargetProperty.

Voici un exemple, très simple, d’animation :

<DoubleAnimation SpeedRatio="5" [Link]="m_BoutonAnime"


[Link]="Width" From="0" To="200" />

Ici, on utilise une DoubleAnimation pour modifier la valeur de la propriété Width de notre
contrôle nommé m_BoutonAnime.
On notera au passage l’utilisation de la propriété SpeedRatio, qui vous permet de spécifier à
quelle vitesse doit s’exécuter votre animation.

Voici une liste des différentes animations possibles que vous pouvez utiliser dans vos
applications WPF :
o ByteAnimation : Ce type d’animation vous permet d’animer la valeur d’une
propriété de type Byte,
o ColorAnimation : Vous permet d’animer la valeur d’une propriété de type
Color,
o DoubleAnimation : Est utilisé pour animer la valeur d’une propriété de type
Double,
o Etc…

Là encore, la quantité d’animation possible est incroyablement longue : c’est pourquoi je ne


vous en montre que quelques-unes….

Thomas LEBRUN
[Link] 20
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Nous allons maintenant voir les KeyFrames, qui peuvent être utilisés avec vos animations.

Les KeyFrames sont utilisés pour définir des « étapes » lors de votre animation.
En effet, vous allez pouvoir définir une animation qui dure, au total, 10 secondes, et indiquer
qu’une animation doit se produire à 2 secondes, une autre animation doit être déclenchée à 7
secondes, etc…. Tout cela, en utilisant des KeyFrames, sorte de point d’arrêt de vos
animations.

Voyons une animation qui utilise les KeyFrames :

<DoubleAnimationUsingKeyFrames SpeedRatio="5"
[Link]="m_BoutonAnime"
[Link]="Width" Duration="[Link]">
<LinearDoubleKeyFrame KeyTime="[Link]" Value="360" />
</DoubleAnimationUsingKeyFrames>

Etudions cette animation d’un peu plus près :


Nous utilisons une DoubleAnimationUsingKeyFrame, c’est-à-dire une animation dans
laquelle nous allons pouvoir spécifier des étapes intermédiaires.
Sur cette animation, nous spécifions une LinearDoubleKeyFrame, qui vous permet d’animer
la valeur d’une propriété de type Double, suivant une interpolation linéaire.
Nous précisons, pour cette étape, la valeur qui doit être atteinte (dans notre cas 360), au
moyen de l’attribut Value. Enfin, grâce à l’attribut KeyTime, on indique que cette valeur doit
être attente au bout de la valeur indiquée (ici, deux secondes).

Comme vous pouvez le voir, les KeyFrames sont relativement simples à utiliser. Et, dans une
animation qui utilise les KeyFrames, rien ne nous empêche d’utiliser plusieurs « étapes » en
même temps :

<DoubleAnimationUsingKeyFrames SpeedRatio="5"
[Link]="m_BoutonAnime"
[Link]="Width" Duration="[Link]">
<LinearDoubleKeyFrame KeyTime="[Link]" Value="360" />
<LinearDoubleKeyFrame KeyTime="[Link]" Value="500" />
</DoubleAnimationUsingKeyFrames>

Maintenant, si vous voulez utiliser plusieurs animations en même temps, vous serez tentez
d’écrire quelque chose comme cela :

<DoubleAnimation SpeedRatio="5" [Link]="m_BoutonAnime"


[Link]="Width" From="0" To="200" />
<DoubleAnimation SpeedRatio="5" [Link]="m_BoutonAnime"
[Link]="Height" From="0" To="200" />

Ici, rien de bien extraordinaire : on déclare deux DoubleAnimation, on affecte la valeur de


leurs attributs et on regarde le résultat. A la fin de la première animation, la deuxième se
lance, ce qui parait logique. Mais comment faire si vous souhaitez lancer les deux animations
en même temps, en parallèle ?
La réponse, qui n’est pas évidente à première vue, passe par l’utilisation d’un objet que nous
n’avons pas encore vu dans cet article : un ParallelTimeline.

Thomas LEBRUN
[Link] 21
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Grâce au ParallelTimeline, vous avez la possibilité d’englober des animations qui


s’exécuteront en parallèle.

Voyons ce que cela donne, si on reprend l’exemple précédent :

<ParallelTimeline>
<DoubleAnimation SpeedRatio="5"
[Link]="m_BoutonAnime"
[Link]="Width" From="0" To="200" />
<DoubleAnimation SpeedRatio="5"
[Link]="m_BoutonAnime"
[Link]="Height" From="0" To="200" />
</ParallelTimeline>

A première vue, pas de grandes différences, mis à part l’utilisation de l’élément


ParallelTimeline.
Cependant, si vous exécutez ce bout de code, vous vous apercevrez que les deux animations
s’animent en même temps, et que la seconde n’attend pas la fin de la première pour pouvoir
démarrer.

Maintenant que nous avons vu les animations, et leur fonctionnement, jetons un œil sur les
transformations.

h. Les transformations
Les transformations sont l’autre élément que vous pouvez utiliser si vous souhaitez donner
plus de vie à vos applications.

Il existe plusieurs types de transformation. On peut, par exemple, citer :


o les TranslateTransform
o les RotateTransform
o les ScaleTransform
o les MatrixTransform
o les SkewTransform
o les TransformGroup

Voyons cela d’un peu plus près ...

Les TranslateTransform, tout d’abord, sont utilisées pour translater un objet. On indique
donc la position en X et la position en Y que notre objet doit avoir, par rapport à son point de
départ, et on assiste ainsi à son déplacement.
Voici un petit exemple :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<TranslateTransform X="100" Y="200" />
</[Link]>
</Rectangle>

Thomas LEBRUN
[Link] 22
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Comme celui-ci n’est sans doute pas très parlant, voici une capture d’écran du résultat :

Plutôt sympa non ? ;)

Les RotateTransform sont des transformations qui vous permettent de réaliser, comme vous
le devinez surement, des rotations. Là encore, un bout de code et une image seront plus
explicites qu’un long roman :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<RotateTransform CenterX="5" CenterY="5" Angle="70" />
</[Link]>
</Rectangle>

Comme vous pouvez le voir, il vous suffit de spécifier les coordonnées en X et en Y du point
de rotation. Ensuite, grâce à l’attribut Angle, vous spécifier de quelle valeur vous voulez
effectuer la rotation de votre contrôle.

Thomas LEBRUN
[Link] 23
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Les ScaleTransform vous offrent la possibilité d’effectuer des redimensionnements de


contrôles. Pour cela, vous devez spécifier, au moyen des attributs CenterX et CenterY, les
coordonnées en X et en Y de la transformation.
Vous pouvez également indiquer le facteur de redimensionnement en X et en Y, au moyen
des attributs ScaleX et ScaleY. L’avantage d’utiliser ces attributs est de pouvoir faire en sorte
que votre transformation subisse également une rotation, bien que cela ne soit pas le but
principal de ce type de transformation.
Pour cela, il vous suffit simplement de spécifier une valeur négative pour les attributs
correspondant aux facteurs de redimensionnement

Voyons cela en exemple :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<ScaleTransform ScaleX="1" ScaleY="-0.5" />
</[Link]>
</Rectangle>

Le résultat de cette transformation est visible sur l’image suivante :

Ici, nous avons utilisé un ScaleY négatif pour faire en sorte que notre rectangle soit inversé.

Les MatrixTransform vous permettent, quand à elles, de créer des transformations


personnalisées, non fournies par les TranslateTransform, RotateTransform, etc…
Une matrice 3x3 est utilisée pour les transformations dans un plan à deux dimensions.

Voici par exemple le résultat d’une transformation de type MatrixTransform :

Thomas LEBRUN
[Link] 24
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Comme vous pouvez le constater, cette transformation est particulière, dans le sens où il s’agit
à la fois d’une rotation et d’un basculement du rectangle. Cela n’est pas possible autrement
qu’en passant par une MatrixTransform.

A titre informatif, voici le code source de cette transformation :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<MatrixTransform Matrix="1 2 2 1 1 1" />
</[Link]>
</Rectangle>

Les MatrixTransform vous offrent donc la possibilité d’utiliser des transformations


complexes dans vos applications. Cela vous donne, par conséquent, la possibilité de n’avoir
presque plus aucune limite !
Cependant, ce sont des objets relativement complexes à utiliser et, à moins d’employer des
outils (tels que Sparkle), vous risquez de passer beaucoup de temps sur la création d’une
MatrixTransform.

Un autre type de transformation qui est disponible dans WPF est la SkewTransform.
Ce type de transformation est utilisé pour faire pivoter votre contrôle suivant un ou deux
axes : l’axe des X et l’axe des Y.
Grâce à l’attribut AngleX, vous allez pouvoir spécifier le degré d’inclinaison de votre
contrôle, par rapport à l’axe des Y.
Inversement, l’attribut AngleY vous permet de définir le degré d’inclinaison de votre
contrôle, par rapport à l’axe des X.

Petites démonstrations : Ce code

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<SkewTransform AngleX="20" />
</[Link]>
</Rectangle>

Vous permet d’obtenir ce résultat :

Thomas LEBRUN
[Link] 25
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Inversement, ce bout de code :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<SkewTransform AngleY="20" />
</[Link]>
</Rectangle>

Vous donne ceci, comme résultat :

Bien entendu, rien ne vous empêche d’utiliser les deux axes (X et Y) pour appliquer votre
transformation :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<SkewTransform AngleX="20" AngleY="20" />
</[Link]>
</Rectangle>

Et observer ce que cela donne :

Comme vous l’imaginez surement, on peut très vite arriver à créer des transformations qui
donneront à vos applications un style plutôt impressionnant ;)

Thomas LEBRUN
[Link] 26
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Pour finir les transformations, il ne me reste plus qu’a vous parler des TransformGroup.

Pour comprendre de quoi il s’agit, essayer tout simplement ce bout de code :

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<ScaleTransform ScaleX="1" ScaleY="-0.5" />
<SkewTransform AngleX="20" AngleY="20" />
</[Link]>
</Rectangle>

Si vous compilez ceci, vous devriez avoir ce message :

The 'Transform' object already has a child and cannot add


'SkewTransform'. 'Transform' can accept only one child

Ainsi que cet avertissement :

The element '[Link]' in namespace


'[Link] has
invalid child element 'SkewTransform' in namespace
'[Link]

En effet, vous ne pouvez pas utiliser deux transformations simultanément de cette façon.
Pour pouvoir le faire, vous devrez utiliser (vous l’avez compris je suppose), les
TransformGroup.

<Button Name="m_BoutonMirroir" />


<Rectangle Name="RectangleMirroir">
<[Link]>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-0.5" />
<SkewTransform AngleX="20" AngleY="20" />
</TransformGroup>
</[Link]>
</Rectangle>

Et là, plus de problèmes ! Vous pouvez utiliser un, deux, trois, etc… bref, autant de
transformations que vous voulez, tant que celles-ci sont comprises dans un
TransformGroup.

Thomas LEBRUN
[Link] 27
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

i. WPF et la 3D
L’une des grandes forces de WPF est de pouvoir utiliser non seulement des objets 2D, mais
également des objets en 3D (trois dimensions).
Vous allez donc pouvoir utiliser dans vos applications des objets qui, habituellement, ne sont
utilisables qu’en deux dimensions (par exemple, une image, une ListBox, etc…)

Note : Travailler avec des objets en trois dimensions n’est pas une chose aisée et nécessite
quelques connaissances préalables sur le sujet. Je vais tenter de rendre cette partie la plus
simple et la plus claire possible, mais n’hésitez surtout pas à consulter la documentation du
SDK (Software Development Kit) pour de plus amples informations, plus « techniques » sur le
sujet.

L’objet qui va nous permettre de mettre un peu plus de dimension dans nos applications est un
objet particulier, le Viewport3D, qui fonctionne comme une fenêtre classique, mais en trois
dimensions.

Avant de commencer, voici une image qui va vous permettre de comprendre comment
visualiser les axes des coordonnées X, Y et Z, dans un plan en trois dimensions, par rapport à
un plan en deux dimensions :

Parce qu’une même scène en trois dimensions semble différente suivant le point de vue
(autrement dit la position) de celui qui la regarde, vous devez, au moyen de la classe Camera,
spécifier ce point de vue pour une scène 3D.

Vous allez pouvoir spécifier, pour une Camera, sa position dans le plan en trois dimensions,
sa direction, son champ de vision (il s’agit d’un angle), et un vecteur qui définit le haut de la
scène.
Le schéma suivant vous permettra de mieux comprendre de quoi il s’agit :

Thomas LEBRUN
[Link] 28
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Ici, on s’aperçoit que la caméra est centrée sur l’axe des Z, qu’elle regarde dans la direction
inverse de l’axe des Z (donc dans la direction –Z), et que le haut de la scène est définit à +Y.

Vous pouvez utiliser plusieurs types de Camera mais nous allons en voir deux plus en détails :
o la PerspectiveCamera
o l’OrthograficCamera

La PerspectiveCamera, tout d’abord, nous permet de définir une caméra qui se « projette »
autour de la scène. Le schéma ci-dessus représente justement le dessin d’une
PerspectiveCamera.

L’OrthograficCamera, quand à elle, définit une projection orthogonale d’un modèle en trois
dimensions, vers une surface visuelle en deux dimensions.
Ce type de caméra est très similaire à la PerspectiveCamera : en effet, là encore vous allez
pouvoir spécifier une direction, un point de vue, etc….Cependant, L’OrthograficCamera
définit une vue dont les cotés sont parallèles au lieu d’une vue dont les cotés finissent par se
rejoindre en un point.
Pour bien comprendre cette notion, observez le dessin suivant :

Dans le premier cas, les cubes sont alignés, grâce à une OrthograficCamera, de façon à ce
qu’ils soient tous parallèles.
Dans le deuxième cas, on voit bien que, à l’aide d’une PerspectiveCamera, on a disposé les
cubes de façon à ce que ceux-ci ne soient pas parallèles.
Pour vous en convaincre, regardez cette image, qui vous montre bien que, dans un cas, les
deux traits ne se rejoindront jamais (utilisation d’une OrthograficCamera), tandis que dans
le deuxième cas, ils ne tarderont pas à se croiser (utilisation d’une PerspectiveCamera) :

Pour faire simple, retenez qu’avec une OrthograficCamera, la distance d’un objet n’influe
pas sur sa taille à l’écran.

Maintenant que nous avons vu la théorie, voyons un peu la pratique, pour apprendre comment
utiliser (entre autre) les Viewport3D ainsi que les Camera.

Thomas LEBRUN
[Link] 29
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Considérez le bout de code suivant :

<!--
On ajoute une caméra pour la vue 3D
-->
<Viewport3D Focusable="True" ClipToBounds="True"
Name="ViewPortLisBox3D">
<[Link]>
<PerspectiveCamera
FarPlaneDistance="50"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="0.0,2.5,10.0"
LookDirection="0.0,-2.5,-9.0"
FieldOfView="45" />
</[Link]>
</Viewport3D>

Ici, on se contente d’ajouter une caméra, de type PerspectiveCamera, à notre application.


Comme vous le devinez rapidement, l’attribut Position nous sert à indiquer, dans le plan en
trois dimensions, les coordonnées de notre caméra.
L’attribut LookDirection, quand à lui, nous permet de définir la direction dans laquelle notre
caméra doit regarder.
UpDirection vous offre la possibilité d’indiquer où se situe le haut de la scène, tandis que
FieldOfView est utilisé pour définir le champ de vision, de la caméra, en degré.
FarPlaneDistance et NearPlaneDistance ont des rôles bien particuliers.
NearPlaneDistance est en effet chargé de définir la distance qui sépare la caméra du plan le
plus proche de la scène.
A l’inverse, FarPlaneDistance est utilisé pour définir la distance entre la caméra et le plan le
plus éloigné de la scène.

Voici un petit aperçu de ce que vous pouvez obtenir : pour l’exemple, j’ai utilisé un
composant particulier, une ListBox dans laquelle on peut stocker des vidéos et où les éléments
sont disposés autour d’un cylindre. Je vous laisse apprécier le résultat :

Thomas LEBRUN
[Link] 30
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Vous avez également la possibilité d’illuminer votre scène, c’est-à-dire de rendre certaines
surfaces de votre scène visible. Pour cela, il vous faut utiliser des objets de la classe Ligth, tel
que :
o AmbientLigth, qui fournit une lumière ambiante, utilisée pour illuminer tous les
objets de la scène, quelque soit leur position ou leur orientation :

<Viewport3D Focusable="True" ClipToBounds="True"


Name="ViewPortLisBox3D">
<ModelVisual3D>
<[Link]>
<AmbientLight Color="Red" />
</[Link]>
</ModelVisual3D>
</Viewport3D>

o DirectionalLigth, qui illumine la scène comme une source lumineuse distante. La


direction des lumières est indiquée via l’attribut Direction, qui est un vecteur 3D :

<Viewport3D Focusable="True" ClipToBounds="True"


Name="ViewPortLisBox3D">
<ModelVisual3D>
<[Link]>
<DirectionalLight Color="Yellow" Direction="-
1.0,0.0,0.0" />
</[Link]>
</ModelVisual3D>
</Viewport3D>

o PointLigth, qui est utilisé pour illuminer un point de votre scène. Les objets de la
scène seront illuminés en fonction de leur position et de leur distant. L’attribut Range
est utilisé pour spécifié à partir de quelle distance la lumière n’a plus d’effet :

<Viewport3D Focusable="True" ClipToBounds="True"


Name="ViewPortLisBox3D">
<ModelVisual3D>
<[Link]>
<PointLight Color="Yellow" Range="10"
Position="0.0,2.5,10.0" />
</[Link]>
</ModelVisual3D>
</Viewport3D>

o SpotLigth, qui hérite de PointLigth, projette une lumière via un cône, dont vous
définissez la taille du point de départ et celle du point d’arrivée :

<Viewport3D Focusable="True" ClipToBounds="True"


Name="ViewPortLisBox3D">
<ModelVisual3D>
<[Link]>
<SpotLight Color="Yellow" Direction="0,1,0"
OuterConeAngle="5" InnerConeAngle="50" Position="0.0,2.5,10.0" />
</[Link]>
</ModelVisual3D>
</Viewport3D>

Thomas LEBRUN
[Link] 31
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Un autre objet fort utile, lorsque vous faîte de la 3D, est le ScreenSpaceLine3D.
Cet objet vous permet de créer des polygones en trois dimensions. Utilisé correctement, il
peut vous permettre de dessiner beaucoup de figure géométrique :

<Viewport3D Focusable="True" ClipToBounds="True"


Name="ViewPortLisBox3D">
<ModelVisual3D>
<[Link]>
<ScreenSpaceLines3D Color="Blue"
Thickness="2.0" Points="2.0, 2.3, 0.0, -2.0, 2.3, 0.0" />
</[Link]>
</ModelVisual3D>
</Viewport3D>

Ici, nous utilisons un ScreenSpaceLine3D pour créer une simple ligne, de couleur bleue.
Avec l’attribut Thickness, nous définissons l’épaisseur du trait qui sera utilisé pour afficher
notre ligne.
L’attribut Points nous permet de définir les points de notre figure.

Maintenant, si vous souhaitez pouvoir utiliser plusieurs éléments pour animer vos objets en
trois dimensions, vous allez être obligé d’utiliser un Model3DGroup :

<Viewport3D Focusable="True" ClipToBounds="True"


Name="ViewPortLisBox3D">
<ModelVisual3D>
<[Link]>
< Model3DGroup>
<ScreenSpaceLines3D Color="Blue"
Thickness="2.0" Points="2.0, 2.3, 0.0, -2.0, 2.3, 0.0" />
<ScreenSpaceLines3D Color="Red"
Thickness="2.0" Points="2.0, -2.0, 0.0, -2.0, -2.0, 0.0" />
<ScreenSpaceLines3D Color="Yellow"
Thickness="2.0" Points="-3.15, 2.0, 0.0, -3.5, -2.0, 0.0" />
<ScreenSpaceLines3D Color="Green"
Thickness="2.0" Points="3.15, 2.0, 0.0, 3.5, -2.0, 0.0" />
</Model3DGroup>
</[Link]>
</ModelVisual3D>
</Viewport3D>

Dans cet exemple, on utilise un Model3DGroup pour insérer, dans notre application, quatre
ScreenSpaceLine3D qui nous serviront à tracer des traits.

Maintenant que nous avons vu comment fonctionne la 3D dans WPF, comment l’implémenter
et comment utiliser certains des objets disponibles pour rendre votre application un peu plus
« réelle », nous allons voir différentes techniques pour effectuer des transformations sur vos
objets 3D.

Thomas LEBRUN
[Link] 32
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Nous avons déjà vu, dans les chapitres précédents, qu’il existe plusieurs objets pouvant servir
à effectuer des transformations sur votre objets 2D :
o les TranslateTransform
o les RotateTransform
o les ScaleTransform
o les MatrixTransform
o les SkewTransform
o les TransformGroup

Et bien sachez que certaines de ces transformations sont également disponible pour les objets
en 3 dimensions :
o les TranslateTransform3D
o les RotateTransform3D
o les ScaleTransform3D
o les MatrixTransform3D
o les Transform3DGroup

Vous l’aurez compris, nous allons nous attarder sur certaines de ces modifications, afin de
vous permettre de comprendre leur comportement et leur utilisation, même si celles-ci sont
très semblables à leur équivalent en deux dimensions.

Les TranslateTransform3D sont utilisées pour permettre à vos objets 3D d’effectuer des
translations dans le plan à trois dimensions.
Regarder cette image pour vous permettre de comprendre de quoi il s’agit :

On a donc bien un déplacement, une translation de l’objet, suivant les axes X, Y et Z.


Illustrons cet exemple par un bout de code :

<Viewport3D Focusable="True" Name="ViewPortLisBox3D">


<ModelVisual3D>
<[Link]>
<GeometryModel3D>
<[Link]>
<TranslateTransform3D OffsetX="2" OffsetY="0" OffsetZ="0" />
</[Link]>
</GeometryModel3D>
</[Link]>
</ModelVisual3D>
</Viewport3D>

Thomas LEBRUN
[Link] 33
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Les TranslateTransform3D possèdent plusieurs attributs, dont les attributs OffsetX, OffsetY,
et OffsetZ, qui nous permettent d’indiquer quelles seront les coordonnées de notre objet,
après la translation.

A noter que la transformation MatrixTransform3D est également disponible, et qu’elle


permet de spécifier des transformations plus précises, car vous indiquez vous-même la
matrice exacte de points que votre transformation doit appliquer à votre objet.

Jetons maintenant un œil sur les RotateTransform3D, qui vous permettront d’effectuer, sur
vos objets 3D, des rotations. Dans ce type de transformation, il est commun de spécifier l’axe
et l’angle de rotation. Vous utilisez, pour cela, une Rotation3D et plus précisément, la
propriété Rotation de cette classe :

<Viewport3D Focusable="True" Name="ViewPortLisBox3D">


<ModelVisual3D>
<[Link]>
<GeometryModel3D>
<[Link]>
<RotateTransform3D>
<[Link]>
<AxisAngleRotation3D Angle="60" Axis="0,10,0" />
</[Link]>
</RotateTransform3D>
</[Link]>
</GeometryModel3D>
</[Link]>
</ModelVisual3D>
</Viewport3D>

Comme vous pouvez le constater, l’axe de rotation est définit ici au moyen de la propriété
Axis, qui prend en paramètre un ensemble de 3 points servant à indiquer les coordonnées de
notre axe. La propriété Angle permet de spécifier l’angle de rotation de notre axe.

Voici une image pour vous donner un aperçu du résultat possible :

Les ScaleTransform3D vous offrent la possibilité d’appliquer des agrandissements et des


réductions, à vos objets en trois dimensions.
Voici, par exemple, l’image d’un cube, sur lequel on a appliqué deux ScaleTransform3D. La
première sert à agrandit le cube, et la deuxième est utilisé pour réduire la taille de notre objet.

Thomas LEBRUN
[Link] 34
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Pour appliquer une transformation de type ScaleTransform3D, vous devez spécifier la valeur
des axes X, Y et Z à partir d’un point central. Voyons, par exemple, le code qui a été utilisé
pour générer le cube le plus petit :

<Viewport3D Focusable="True" Name="ViewPortLisBox3D">


<ModelVisual3D>
<[Link]>
<GeometryModel3D>
<[Link]>
<ScaleTransform3D CenterX="10" CenterY="20" CenterZ="5"
ScaleX="0.5" ScaleY="0.5" ScaleZ="0.5" />
</[Link]>
</GeometryModel3D>
</[Link]>
</ModelVisual3D>
</Viewport3D>

Si vous voulez multiplier les transformations sur des objets 3D, vous devez utiliser des
Transform3DGroup. Ceux-ci vous permettent de manipuler, une à plusieurs
transformations, en même temps.

Voici un petit exemple, qui reprend l’utilisation d’une RotateTransform3D et d’une


ScaleTransform3D :

<Viewport3D Focusable="True" Name="ViewPortLisBox3D">


<ModelVisual3D>
<[Link]>
<GeometryModel3D>
<[Link]>
<Transform3DGroup>
<RotateTransform3D>
<[Link]>
<AxisAngleRotation3D Angle="60"
Axis="0,10,0" />
</[Link]>
</RotateTransform3D>
<ScaleTransform3D CenterX="10" CenterY="20"
CenterZ="5" ScaleX="0.5" ScaleY="0.5" ScaleZ="0.5" />
</Transform3DGroup>
</[Link]>
</GeometryModel3D>
</[Link]>
</ModelVisual3D>
</Viewport3D>

Thomas LEBRUN
[Link] 35
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Au travers de cette partie, j’ai tenté de vos expliquer les différents concepts et mises en œuvre
sur tout ce qui touche à la 3D dans WPF. Comme je vous l’ai dit au début, cette partie est
sans doute l’un des plus complexes à maitriser, surtout si vous n’en avez jamais fait
auparavant.

Cependant, des outils sont là pour vous aider : j’ai déjà cité Sparkle, mais sachez qu’il existe
aussi un outil, développé par ElectricRain ([Link] qui se nomme ZAM3D et
qui vous permet de réaliser, très simplement, des éléments d’interface en trois dimensions.

Voici un aperçu de l’interface de ZAM3D :

Et une image vous montrant le code généré :

Thomas LEBRUN
[Link] 36
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

j. Le binding
Pour comprendre le DataBinding, dans WPF, une notion est importante à comprendre et à
bien maîtriser :

Il s’agit du DataContext : dans WPF, ce terme représente un concept, qui autorise les
éléments enfants à hériter de l’information de leur élément parent.

Voyons un petit exemple :

<Grid>
<[Link]>
//
</[Link]>
</Grid>

De cette façon, tous les éléments insérés dans la grille (représentée par le contrôle Grid)
auront pour source de données l’objet que vous aurez indiqué dans l’attribut DataContext.
Même si cela peut vous paraitre complexe pour le moment, je vais tenter de clarifier la chose
par la suite, avec d’autres exemples un peu plus parlants.

Attardons maintenant sur un objet bien pratique pour interroger une source de données au
format XML : le XmlDataProvider.
Voyons directement un exemple, qui sera plus parlant que des dizaines de lignes de texte :

<Grid>
<[Link]>
<XmlDataProvider
Source="[Link]
x:Key="MyXmlRssSource" />
</Grid. Resources >
</Grid>

Comme vous pouvez le constater, cet objet est relativement simple à utiliser: il vous suffit
d’indiquer l’endroit où se situe la source des données, au moyen de l’attribut Source, et
éventuellement, la requête XPath que vous voulez effectuer, toujours au moyen d’un attribut,
l’attribut XPath.

Une fois votre source de données définie, il ne vous reste plus qu’à la lier à votre grille (ou
autre composant). Pour cela, vous allez utiliser l’attribut DataContext, que nous avons vu
juste avant !

<Grid>
<[Link]>
<Binding Source="{StaticResource MyXmlRssSource}"
XPath="/rss/channel" />
</[Link]>
</Grid>

Ici, nous définissons que la source de données communes à tous les enfants de notre grille
sera en fait notre source de données au format XML.

Thomas LEBRUN
[Link] 37
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

A partir de là, il ne vous reste plus qu’à lier les propriétés qui vous intéressent en faisant du
Binding (liaison de données).
L’exemple suivant est suffisament complet et commenté pour parler de lui-même. Je signale
simplement qu’il s’agit d’un simple lecteur RSS développé en quelques minutes à peine :

<Grid>
<[Link]>
<XmlDataProvider
Source="[Link]
x:Key="MyXmlRssSource" />

<!—
On définit un DataTemplate pour notre ListBox:
On choisit donc la façon dont seront afficher les
données
On utilise un TextBlock dont la propriété Text est
bindée à l'élément title
car le context de la ListBox, dans le DataTEmplate, est
la collection d'item
-->
<DataTemplate x:Key="MyListBoxItemTemplate">
<TextBlock Text="{Binding XPath=title}" />
</DataTemplate>
</Grid. Resources >

<[Link]>
<Binding Source="{StaticResource MyXmlRssSource}"
XPath="/rss/channel" />
</[Link]>

<[Link]>
<ColumnDefinition Width="0.4*" />
<ColumnDefinition Width="0.6*" />
</[Link]>

<DockPanel [Link]="0">
<!—
On indique la source de données de notre ListBox et
son ItemTemplate
-->
<ListBox ItemsSource="{Binding XPath=item}"
ItemTemplate="{StaticResource MyListBoxItemTemplate}"
x:Name="MyListBoxOfRss" IsSynchronizedWithCurrentItem="True"
SelectedIndex="0" />
</DockPanel>

<DockPanel [Link]="1">
<!—
Le DataContext de notre TextBlock correspond à
l'item sélectionné dans la ListBox
Et on binde le texte sur le description de cet
élément.
-->
<TextBlock DataContext="{Binding
ElementName=MyListBoxOfRss, Path=SelectedItem}" Text="{Binding
XPath=description}" x:Name="TextBlocDescription" />
</DockPanel>
</Grid>

Thomas LEBRUN
[Link] 38
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Voyons maintenant un autre objet fort utile lorsque vous faites du Databinding :
l’ObjectDataProvider.
Cet objet propose les mêmes fonctionnalités, et même bien plus, que l’ObjectDataSource,
disponible dans le Framework .NET 2.0.
En effet, grâce à lui, vous allez pouvoir définir un objet comme étant la source de vos
données, mais vous allez également pouvoir :
o passer des paramètres au constructeur de votre objet (celui utilisé comme source de
données)
o vous lier à une méthode (qui peut, ou non, prendre des paramètres)
o remplacer l’objet qui sert de source de données
o créer l’objet servant de source de données de façon asynchrone

Avant d’allez plus loin dans les détails, voici un exemple, simple, de déclaration d’un
ObjectDataProvider :

<ObjectDataProvider ObjectType="{x:Type m:MyPhoto}"


x:Key="MyPhotoDSO" />

(J’ai repris, pour cet exemple, la classe MyPhoto que j’ai introduit lors de la partie 4D).

Avec ce code, nous définissons une source de données, qui s’appellera MyPhotoDSO, et, au
moyen de l’attribut ObjectType, nous définissons le type des données à utiliser comme
source (dans notre cas, des données de type MyPhoto).

Etudions donc maintenant, d’un peu plus près, les fonctionnalités avancées offertes par cet
objet.

Commençons par la plus simple : la possibilité de passer des paramètres au constructeur de


votre objet.
Pour cela, il faut passer par l’attribut ConstructorParameters de votre
ObjectDataProvider :

<ObjectDataProvider ObjectType="{x:Type m:MyPhoto}"


x:Key="MyPhotoDSO" />
<[Link]>
<s:Int32>1</s:Int32>
<s:String>Ma Photo</s:String>
</[Link]>
</ObjectDataProvider>

Avec cet attribut, qui est en fait une collection, vous pouvez spécifier l’ensemble de
paramètres à passer à votre constructeur, en indiquant leur type (Int32, String, Float, etc…).
A noter que le type des paramètres est précédé du namespace s. Pour rappel, cet espace de
nom est déclaré lors de la déclaration de notre élément Window :

<Window x:Class="DemosWPF.Window1"
xmlns=[Link]
xmlns:x=[Link]
Title="DemosWPF" Height="768" Width="1024"
WindowStartupLocation="CenterScreen"
xmlns:s="clr-namespace:System;assembly=mscorlib"
>

Thomas LEBRUN
[Link] 39
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Pour utiliser cet ObjectDataProvider, cela se fait de façon très simple :

<DataTemplate DataType="{x:Type m:MyPhoto}">


<Image Source="{Binding Source={StaticResource MyPhotoDSO},
Path=SourcePhoto}" />
</DataTemplate>

Ici, on créé un DataTemplate, qui nous servira à définir comment nous devons afficher les
éléments de type MyPhoto. On indique que ces éléments doivent être affichés dans un
contrôle de type Image, dont la source est liée à notre source de données, nommée
MyPhotoDSO et plus particulièrement, à la propriété SourcePhoto.

Et voila ! A partir de là, vous avez spécifié que vous vouliez utiliser un objet de type
MyPhoto, et plus précisément l’objet qui a comme propriété l’identifiant ayant pour valeur
« 1 » et la description, avec comme valeur « Ma photo ». Ainsi, lors de la liaison
(« Binding »), on ne va afficher qu’une photo, celle dont les paramètres ont été passés en
paramètre.

Voyons maintenant la possibilité qui nous est offerte, par l’ObjectDataProvider, de nous lier
(« binder ») à une commande.
Là encore, nous allons devoir utiliser plusieurs attributs particuliers :
o MethodName, prend en paramètre le nom de la méthode à laquelle vous voulez vous
lier. Autrement dit, vous spécifier ici le nom de la méthode, sur votre objet, que vous
voulez exécuter.
o ObjectInstance, vous permet d’indiquer l’instance, en cours d’exécution, avec
laquelle vous voulez travailler.
o MethodParameters, représente la collection de paramètres que vous pouvez,
éventuellement, passer à votre méthode.

Pour concrétiser cette théorie, reprenons notre classe MyPhoto et ajoutons-y une méthode qui
va afficher les informations sur la photo dont l’identifiant est passé en paramètre:

public void DisplayPhotoInformations(int Id)


{
// Juste pour la démo: Ne pas refaire
if (Id == 1)
{
[Link]("Photo n°: {0}", [Link]);
[Link]("Description: {0}", [Link]);
}
}

Voyons comment nous pouvons nous lier à cette méthode. Pour cela, il nous faut créer un
autre ObjectDataProvider :

<ObjectDataProvider ObjectInstance="{StaticResource MyPhotoDSO}"


MethodName="DisplayPhotoInformations" x:Key="MyPhotoDSOMethod">
<[Link]>
<s:Int32>1</s:Int32>
</[Link]>
</ObjectDataProvider>

Thomas LEBRUN
[Link] 40
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Ici, nous créons un ObjectDataProvider, nommé MyPhotoDSOMethod, qui va appeler la


méthode DisplayPhotoInformations, de notre objet MyPhotoDSO.

Pour utiliser cet objet nouvellement créé, voici comment nous pouvons faire :

<Label Content="{Binding Source={StaticResource MyPhotoDSOMethod}}"


/>

C’est simple, rapide mais efficace !

Voyons à présent la troisième fonctionnalité de cet objet : le remplacement de l’objet utilisé


comme source de données.

Imaginez ce scénario :
Vous avez à votre disposition une ListBox dont la source de données est liée à une collection
d’images. Comment pourriez-vous faire pour changer le type des éléments de votre source de
données, et utiliser des chaines des caractères à la place des images ?
Une solution serait de créer deux sources de données (une pour les images et une pour les
chaines de caractères), et de sélectionner l’une ou l’autre selon vos besoins.
Mais la solution la plus élégante est très certainement d’utiliser un ObjectDataProvider et de
modifier, dynamiquement, la valeur de sa propriété ObjectType.
En effet, si celle-ci est modifiée, votre ObjectDataProvider sera aussitôt averti que la source
de données à changer et se mettra à jour automatiquement.

Pour finir cette partie, nous allons voir, rapidement, comment nous pourrions faire pour créer
notre objet, source de données, de façon asynchrone.

Vous aurez sans doute remarquez l’un des attributs possibles de l’ObjectDataProvider :

IsAsynchronous="True"

Celle-ci vous permet d’indiquer si vous désirez que le chargement de vos données se déroule
dans le même thread que votre application, ou bien dans un thread différent.
A noter que, par défaut, l’ObjectDataProvider est synchrone et le XmlDataProvider est
asynchrone.

Note : Je n’ai traité ici qu’une partie du DataBinding avec Windows Presentation Foundation.
Le domaine est tellement vaste qu’il mériterait un article (ou un livre) à lui tout seul.
Cependant, si vous voulez plus de détails sur l’ObjectDataProvider, et le DataBinding, en
général, avec Windows Presentation Foundation, je ne peux que vous conseiller le site Web
de Beatriz Costa : [Link] et plus particulièrement ce message, qui traite
spécifiquement de l’ObjectDataProvider : [Link]
[Link]

Thomas LEBRUN
[Link] 41
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

k. Textes et documents
Le support du texte et des documents a complètement été remanié dans Windows Presentation
Foundation.
Ce que l’on peut appeler le « Framework de Texte » de WPF supporte désormais :
o des animations de texte qui utilisent au mieux les matériaux compatible DirectX
o utilisation optimisée de la technologie ClearType
o l’affichage indépendant de la résolution
o l’utilisation de l’Unicode pour tous les textes
o etc….

Bien entendu, cette liste n’est pas exhaustive : beaucoup d’autres fonctionnalités sont
supportées et fournies par WPF.

Pour inclure du texte dans vos applications, vous avez accès à de nombreuses APIs, telles que
les Labels, les TextBox, les TextBlock, etc….
Ces éléments sont les éléments de base de l’interface utilisateur, et offrent un moyen simple et
rapide d’utiliser du texte. Ils possèdent des propriétés telles que FontFamily, FontSize et
FontStyle, qui vous permettent de définir, précisement, la police à utiliser :

<TextBlock FontFamily="Lucida Console" FontStyle="Oblique"


FontSize="15" Text="TextBloc de test" />

Au travers de ce bout de code, nous avons définit le type de police à utiliser (Lucida
Console), le style à appliquer (Oblique) et la taille de la police (15).
Le résultat, en image :

Comme indiqué juste ci-dessus, WPF supporte, de façon améliorée, la technologie


ClearType. Cette technologie, développée par Microsoft, permet d’améliorer la lisibilité et la
lecture de texte, sur les écrans LCD (Liquid Crystal Display), tels que les écrans d’ordinateurs
portables, les écrans de Pocket PC ou bien certains écrans plats.

Je vous épargnerai ici les détails (complexes) de l’implémentation et du fonctionnement de la


technologie ClearType, mais sachez qu’une des améliorations qu’elle apporte dans Windows
Presentation Foundation est « l’anti-aliasing par rapport à l’axe des Y ».

ClearType, lorsqu’elle est utilisé avec GDI (Graphic Device Interface) sans l’anti-aliasing via
l’axe Y, offre une meilleure résolution sur l’axe des X. C’est bien sur l’inverse lorsque vous
utiliser la technologie de l’anti-aliasing suivant l’axe des Y.

Thomas LEBRUN
[Link] 42
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Pour voir une démonstration, regarder ces images : sur celles de droite, les contours sont
lisses, l’image est nette. On a donc utilisé ClearType, dans notre application WPF, pour cette
image :

Grande nouveauté également : vous avez également accès aux classes


FlowDocumentReader, FlowDocumentPageViewer, FlowDocumentScrollViewer et
FlowDocument. Celles-ci vous permettent d’afficher et de formater du contenu en utilisant
des fonctions avancées ; telle que la pagination et les colonnes.
Vous avez également accès, grâce à l’utilisation de ces classes, à la fonction de recherche,
ainsi qu’au zoom sur votre document.

Voici un exemple d’utilisation de ces contrôles :

<FlowDocumentReader>
<FlowDocument>
<Paragraph>
Paragraphe Normal
</Paragraph>

<Paragraph FontSize="25">
Paragraphe avec une taille de 25
</Paragraph>

<Paragraph>
<Bold>
<Italic>Paragraphe en gras et
italique</Italic>
</Bold>
</Paragraph>

<Paragraph>
<LineBreak />
Paragraphe avec un LineBreak (Saut de ligne)
juste avant
</Paragraph>
<Section>
<Paragraph>
Une section qui inclut un paragraphe
</Paragraph>
</Section>

<Paragraph TextIndent="25">
Paragraphe avec un indentation, pour le Texte, de
25
</Paragraph>
</FlowDocument>
</FlowDocumentReader>

Thomas LEBRUN
[Link] 43
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Vous avez également la possibilité d’utiliser des décorations pour vos textes. La classe
TextDecoration est en effet là pour vous permettre d’utiliser des ornements visuels sur vos
textes. Il y a quatre types de décoration de texte disponibles, que je vais vous représenter
grâce à cette image :

Pour spécifier où la décoration doit apparaître, utilisez la propriété Location de votre objet de
type TextDecoration. Pour définir l’apparence de votre décoration, il vous faut passer par la
propriété Pen.
Voici un bout de code vous expliquant comment mettre en application notre décoration :

<TextBlock FontSize="30">
Ceci est une simple décoration
<[Link]>
<!—
On indique que la décoration voulue est située au
dessus du texte
-->
<TextDecoration Location="OverLine"
PenThicknessUnit="FontRecommended">
<[Link]>
<Pen Brush="YellowGreen" Thickness="1" />
</[Link]>
</TextDecoration>
</[Link]>
</TextBlock>

Comme vous le voyez, il suffit d’ajouter une TextDecoration à la collection nommée


TextDecorations, et le tour est joué.
Voici une image du résultat de la décoration précédente :

Bien entendu, vous n’êtes pas limité à une seule décoration. Comme je vous l’ai dit,
TextDecorations est une collection donc, à ce titre, vous pouvez en ajouter autant que vous
voulez, pour avoir, par exemple, quelque chose comme cela :

Thomas LEBRUN
[Link] 44
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Le code qui a servit à créer ces deux décorations est le suivant :

<TextBlock FontSize="30">
Ceci est une riche décoration
<[Link]>
<!—
On indique que la décoration voulue est située au
dessus et dessous du texte
-->
<TextDecoration Location="OverLine"
PenThicknessUnit="FontRecommended">
<[Link]>
<Pen Brush="Blue" Thickness="1" />
</[Link]>
</TextDecoration>

<TextDecoration Location="Underline"
PenThicknessUnit="FontRecommended">
<[Link]>
<Pen Brush="BlueViolet" Thickness="2" />
</[Link]>
</TextDecoration>

</[Link]>
</TextBlock>

Enfin, sachez que rien ne vous empêche d’appliquer, à vos textes, des styles un peu plus
élaborés : nous allons en effet voir la technique utilisée pour réaliser des dégradés de couleurs.

Note : Les dégradés de couleurs seront vus ici avec les décorations de texte, mais sachez que
rien ne vous empêche de les utiliser ailleurs dans vos applications WPF, comme par exemple
pour créer des fonds dégradés, etc… comme le montre cette image :

Thomas LEBRUN
[Link] 45
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Lorsque l’on y réfléchit bien, un dégradé de couleur, qu’est ce que c’est ? Une couleur de
début, une couleur de fin puis on affiche toutes les couleurs du spectre qui sont comprises
entre nos deux bornes.
Et bien c’est ce que WPF nous permet de faire, et cela de façon très simple :

<TextBlock FontSize="30">
Ceci est une très riche décoration
<[Link]>
<!—
On indique que la décoration voulue est un trait de
soulignement
-->
<TextDecoration Location="Underline"
PenThicknessUnit="FontRecommended">
<[Link]>
<Pen Thickness="1.5">
<[Link]>
<LinearGradientBrush Opacity="0.5"
StartPoint="0,0.5" EndPoint="1,0.5">
<[Link]>
<GradientStop Color="Yellow"
Offset="0" />
<GradientStop Color="Red"
Offset="1" />
</[Link]>
</LinearGradientBrush>
</[Link]>

<!—
Pour afficher des pontillés
-->
<[Link]>
<DashStyle Dashes="2"/>
</[Link]>
</Pen>
</[Link]>
</TextDecoration>

<TextDecoration Location="Underline"
PenThicknessUnit="FontRecommended">
<[Link]>
<Pen Brush="BlueViolet" Thickness="2" />
</[Link]>
</TextDecoration>

</[Link]>
</TextBlock>

Ici, nous utilisons un LinearGradientBrush, sur lequel nous précisons les coordonnées du
point de départ (via l’attribut StartPoint) ainsi que les coordonnées du point d’arrivée (au
moyen de l’attribut EndPoint). Nous précisons également quelle doit être l’opacité du trait
qui sera tracé, grâce à l’attribut Opacity.
Concrètement, nous ne faisons que dire : « Je veux tracer un trait, qui doit aller du point A (0,
0.5) au point B (1, 0.5), en étant visible à 50% ».
Ensuite, nous utilisons des GradientStops, qui nous servirons à définir quelle couleur doit
être appliquée lorsque l’on se situe sur la position indiquée.
Pour terminer, nous définissons le style de trait que nous voulons utiliser, via l’élément
DashStyle.
Thomas LEBRUN
[Link] 46
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Le résultat est parlant de lui-même :

On a bien un trait en pointillé, situé en dessous du texte, qui commence en jaune et qui se
termine en rouge !
Bien sur, rien ne vous empêche de rajouter, selon vos besoins, d’autres GradientStops.

Tout ce que l’on a vu à propos des rotations de contrôles WPF est également valable pour le
texte. Ainsi, le code suivant ne pose aucun problème :

<TextBlock FontSize="15">
Un texte transformé
<[Link]>
<RotateTransform Angle="20" />
</[Link]>
<LineBreak />
<LineBreak />
</TextBlock>

Et fournit le résultat suivant :

Pour les animations, c’est la même chose ! Ce qui a été vu pour les contrôles fonctionne tout à
fait pour le texte :

<TextBlock FontSize="15">
Un texte avec une animation
<[Link]>
<RotateTransform Angle="0" x:Name="RotationTextBlock" />
</[Link]>

<[Link]>
<EventTrigger RoutedEvent="[Link]">
<[Link]>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
[Link]="RotationTextBlock"
[Link]="Angle" From="0.0" To="360"
Duration="[Link]" />
</Storyboard>
</BeginStoryboard>
</[Link]>
</EventTrigger>
</[Link]>
</TextBlock>

Thomas LEBRUN
[Link] 47
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Dans cet exemple, nous ne faisons qu’appliquer une transformation de type


RotateTransform, autrement dit une rotation, à un élément de type TextBlock.
Ainsi, lorsque la souris passera sur le TextBlock, nous allons faire varier la propriété Angle de
la rotation, pour la faire passer de 0 à 360 (autrement dit, lui faire faire un tour complet) en 3
secondes.

Bien entendu, WPF vous donne la possibilité d’appliquer, à votre texte, des effets grâce à la
classe TextEffect.
Cette classe vous permet, en effet, de prendre le texte qui est dans une chaîne de caractères et
de le considérer comme s’il s’agissait d’un ou plusieurs groupes de lettres. Vous aller donc
pouvoir appliquer des transformations, animations, etc… à un ou plusieurs groupes de
caractères, composé de une à plusieurs lettres.

<TextBlock FontSize="25">
Texte avec un caractère animé
<[Link]>
<TextEffect PositionStart="12" PositionCount="1">
<[Link]>
<RotateTransform Angle="0"
x:Name="RotationLettreTextBlock" />
</[Link]>
</TextEffect>
</[Link]>

<[Link]>
<EventTrigger RoutedEvent="[Link]">
<[Link]>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
[Link]="RotationLettreTextBlock "
[Link]="Angle" From="0.0" To="360"
Duration="[Link]" />
</Storyboard>
</BeginStoryboard>
</[Link]>
</EventTrigger>
</[Link]>
</TextBlock>

Nous avons donc définit un effet, et plus précisément une RotateTransform, qui sera
appliqué à un groupe de caractères. Pour définir la position de départ de ce groupe de
caractères, nous utilisons la propriété PositionStart de l’objet TextEffect. La propriété
PositionCount nous permet simplement de savoir combien de caractères nous servirons à
composer ce groupe.

Vous avez également la possibilité d’appliquer des effets de relief à vos textes, grâce aux
classes DropShadowBitmapEffect et OutterShadowBitmapEffect. Notez cependant que
l’utilisation de ces classes entrainera la désactivation de la technologie ClearType, au sein de
vos applications WPF.

Thomas LEBRUN
[Link] 48
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

5. WPF /E
Vous l’avez vu jusqu'à maintenant, Windows Presentation Foundation vous permet de réaliser
des applications au design novateur, et cela en quelques minutes seulement.

Mais le but de Microsoft ne s’arrête pas là. En effet, leur objectif est de pouvoir faire en sorte
que les applications WPF puissent s’exécutent sur un maximum de plateformes possibles.
Pour cela, ils ont créé WPF /E (Windows Presentation Foundation /EveryWhere).
Il s’agit d’un sous-ensemble de WPF, qui permet d’exécuter des applications WPF sur
n’importe quel type de plateforme (PC, Mac, Pocket PC, Smartphone, etc..).
Microsoft cible en effet Opéra, FireFox et Internet Explorer sur Windows, mais également
Safari et FireFox sur Mac. Une version pour Linux et Solaris est également envisagée.

Pour arriver à ce résultat, il vous faut créer des applications de type XAML Browser
Application, autrement dit des applications qui s’exécuteront dans un navigateur Internet.
Car, en effet, si l’on y réfléchit bien, quel est le seul type d’applications qu’il est possible
d’exécuter à la fois sous Windows, Linux mais encore Solaris, Pocket PC, etc….
La réponse est bien sur évidente : il s’agit des applications Web.

Au travers de ce chapitre, je vais donc vous parler, un peu plus en détails, de WPF /E.

Les bases étant maintenant établies, nous savons que WPF /E est un sous-ensemble de WPF,
qui a pour objectif de fournir des applications Web tirant parti de toute la puissance de
WinFX : On peut donc espérer, maintenant, des applications Web aussi jolies que des
applications Windows.

A noter : Vous ne pouvez pas, dans vos applications WPF /E, utiliser de contrôles en 3D.

Avant de rentrer plus dans les détails, laissez moi vous montrer quelques images pour
découvrir un aperçu d’applications WPF /E :

Sur cette première image, l’auteur de l’application a créé une horloge dont les aiguilles sont
animées. L’horloge est transparente, ce qui nous permet de voir l’image utilisée en arrière-
plan. Au passage, notez le navigateur Web qui a été utilisé pour la démonstration…

Thomas LEBRUN
[Link] 49
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Regardez à présent cette capture d’écran :

Ici, nous avons affaire à un outil de visualisation vectoriel, qui permet à l’utilisateur de
zoomer et de faire pivoter l’image.

Pour finir, il ne me reste plus qu’à vous montrer cette copie de XAMLPad pour les
applications WPF /E. Il s’agit d’une application DHTML qui incorpore le plugin de
navigation Internet WPF /E, et qui interprète le XAML qui a été saisi dans la zone de texte :

Le rendu de toutes ces images donne l’impression que ces applications ont été réalisées à
l’aide de Flash ou d’une technologie semblable mais pourtant, il s’agit bien d’applications
Web utilisant le moteur graphique de WinFX : Windows Presentation Foundation.

Thomas LEBRUN
[Link] 50
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Voyons à présent, un peu plus en détails, comment fonctionnent les applications de type
XAML Browser Application, autrement dit les applications WPF que vous allez exécuter
dans un navigateur Web.

Première chose à savoir, qui peut paraître logique mais qu’il est bon de rappeler : les
applications WPF /E sont des applications disponibles en ligne uniquement !

Ensuite, vous aurez sans doute remarqué qu’il n’y a pas d’installation, lorsque vous exécutez
une application de ce type. En effet, cela passe par un déploiement ClickOnce, transparent
pour l’utilisateur, et qui n’affiche aucune entrée dans le menu « Démarrer » ou bien dans le
panneau « Ajout/Suppression de programmes » :

Nous avons vu que l’exécution de ces applications se fait au travers d’un navigateur Web : il
suffit donc d’avoir un navigateur Web compatible, ainsi que le Runtime WinFX, pour
pouvoir exécuter des applications WPF /E.

Du côté sécurité, tout à également été prévu : en effet, les applications s’exécutent dans un
contexte sécurisé, ce qui nous permet de ne pas avoir d’avertissement de sécurité.

Pour pouvoir faire fonctionner toute cette mécanique, il nous manque un élément important :
le JavaScript. C’est lui qui représente le lien qui servira à connecter l’applet WPF /E à la
page Web. WPF /E ne possède pas son propre moteur JavaScript. Au lieu de cela :
o il expose des propriétés et des méthodes au JavaScript qui est dans le
navigateur
o il déclenche des évènements que le JavaScript peut manipuler.

Thomas LEBRUN
[Link] 51
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Là encore, une image « récapitulative » de l’architecture de WPF /E sera la bienvenue pour


vous permettre d’assimiler toutes notions :

Voici, par exemple, le code d’une simple application WPF /E :

<Grid>
<TextBlock FontSize="35" FontStyle="Italic" FontWeight="Bold"
VerticalAlignment="Center" HorizontalAlignment="Center" [Link]="0">
Bienvenue dans cette application WPE /F
</TextBlock>

<Button Content="Cliquez ici" VerticalAlignment="Top"


HorizontalAlignment="Center" [Link]="1">
<[Link]>
<RotateTransform Angle="0"
x:Name="MyButtonTransform" />
</[Link]>

<[Link]>
<EventTrigger RoutedEvent="[Link]">
<[Link]>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
[Link]="MyButtonTransform"
[Link]="Angle" From="0" To="360" Duration="[Link]"
/>
</Storyboard>
</BeginStoryboard>
</[Link]>
</EventTrigger>
</[Link]>
</Button>
</Grid>

Thomas LEBRUN
[Link] 52
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Et le résultat obtenu:

Techniquement, vous être maintenant en mesure de réaliser les mêmes applications, que ce
soit en client lourd (applications Windows) ou en client léger (applications Web).

Vous pouvez également « embarquer » votre code XAML dans une simple page Web, et
l’utiliser grâce à du JavaScript.
En voici d’ailleurs un exemple :

<html xmlns="[Link] >


<head></head>
<body>
<script type="text/xaml" id="WpfeControl1Xaml">
<Canvas
xmlns="[Link]
xmlns:x="[Link] >
<Rectangle x:Name="myRect" Fill="orange"
Width="100" Height="100" [Link]="10" [Link]="10"/>
</Canvas>
</script>

<script language="javascript" type="text/javascript">


function clickHandler()
{
// Get text input
var textbox = [Link]("textbox");

// Get the WPF/E plug-in


var wpfeControl =
[Link]("WpfeControl1");

// Get the vector path from inside the WPF/E plug-in


var myRect = [Link]("myRect");

// Set the value of a property on the path


[Link]("Fill", [Link]);
}
</script>

<div>
<input id="textbox" type="text" value="Orange"/>
<button onclick="clickHandler()">Change
Color</button><br />
<embed id="WpfeControl1" height="312px" width="354px"
SourceElement="WpfeControl1Xaml" BackgroundColor="White"
type="application/xcp-plugin"/>
</div>
</body>
</html>

Thomas LEBRUN
[Link] 53
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Dans cet exemple, nous encadrons notre code XAML dans une balise script en spécifiant le
type adéquat : text/xaml.
Ensuite, tout passe par du simple JavaScript :
o On récupère le contenu de notre TextBox
o Ensuite, on récupère notre contrôle WPF /E
o Puis à partir de là, toujours à l’aide de JavaScript, on accède aux contrôles qui sont à
l’intérieur de notre contrôle WPF /E
o Et on termine par travailler avec ces contrôles, en appelant les méthodes adéquates.

Ainsi, on a une complète interaction entre notre code XAML et notre code JavaScript !

Aujourd’hui, Windows Presentation Fondation /EveryWhere est encore un produit jeune,


encore plus que sa version « complète » Windows Presentation Foundation.
Pour preuve, la première CTP (Community Technology Preview) est prévue pour l’été 2006 et
la version RTM (Release To Manufacter) est annoncée pour l’année 2007.

Je n’ai donc fait que « survoler » le sujet, en espérant avoir quelque chose de plus à vous
montrer dans les mois qui viennent.

6. Interopérabilité entre les WindowsForms et WPF :


Nous avons, jusqu'à maintenant, couvert une très grande partie de Windows Presentation
Foundation.
Même si nous ne nous sommes pas forcément attardés sur tous les points, ou bien que nous ne
soyons pas forcément rentrés dans des détails trop complexes, vous avez un bon aperçu du
type d’applications que nous développerons dans les années à venir.

Mais il se peut que certains d’entre vous souhaitent utiliser les capacités de Windows
Presentation Foundation au sein de leurs applications WindowsForms classiques.
Ou bien même, il est possible, en tant que développeurs d’applications de type Windows
Presentation Foundation, vous souhaitiez utiliser des contrôles WindowsForms classiques
(par exemple, les contrôles Calendar ou MonthCalendar, ceux-ci n’étant pas disponibles dans
WPF).

Et bien sachez que cela est possible, grâce à un projet dont le nom de code est : Crossbow.
Crossbow est un projet qui à pour but de permettre l’interopérabilité entre les WindowsForms
et Windows Presentation Foundation. Autrement dit, vous allez pouvoir développer des
applications « hybrides », mêlant à la fois WindowsForms et contrôles WPF.

Concrètement, cela est possible grâce à deux contrôles : WindowsFormsHost et


ElementHost.
WindowsFormsHost est un contrôle WPF qui à la capacité de savoir comment héberger un
contrôle WindowsForms.
A l’inverse, ElementHost est un contrôle qui vous permet d’intégrer, dans vos applications
WindowsForms « classiques », des contrôles WPF.

Thomas LEBRUN
[Link] 54
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Chose très importante à retenir : Lorsque vous mettez en place cette l’interopérabilité, si vous
avez deux contrôles WindowsForms sur une page WPF, et que ceux-ci ne sont pas intégrés
dans un UserControl, alors vous allez devoir utiliser deux WindowsFormsHost, un pour
contrôles WindowsForms.
Inversement, si dans votre application WindowsForms, vous avez plus d’un contrôle WPF,
vous allez devoir utiliser autant de contrôles ElementHost qu’il y a de contrôle WPF.

Autrement dit, les contrôles WindowsFormsHost et ElementHost sont


limités et ne peuvent intégrer qu’un seul contrôle parent.

Ceci étant dit, voyons comment mettre tout cela en pratique !

Commençons par voir comment ajouter un contrôle WindowsForms dans une application
WPF.
La première chose à faire, après avoir créé le projet, est d’ajouter deux références : une à
[Link] (pour pouvoir manipuler des contrôles WindowsForms), et l’autre à
WindowsFormsIntegration.
Cette deuxième référence, qui est disponible via la DLL se trouvant dans le répertoire
C:\Program Files\Reference Assemblies\Microsoft\Avalon\v2.0.50215\ (attention au numéro
de version qui peut changer suivant la CTP que vous utilisez), est nécessaire car elle contient
tout ce dont vous avez besoin pour faire de l’interopérabilité WindowsForms – WPF.
En effet, cette DLL n’est pas ajoutée de base au projet que vous créez car il s’agit toujours,
pour le moment, d’une « Tech Preview », autrement dit d’une version de test uniquement.

Une fois les références ajoutées, nous allons devoir indiquer à XAML où se situent les classes
disponibles dans [Link] et [Link].
Pour cela, nous allons utiliser, dans notre XAML, des instructions de mapping,

<?Mapping XmlNamespace="wfi"
ClrNamespace="[Link]"?>
<?Mapping XmlNamespace="wf" ClrNamespace="[Link]"?>

Ce mapping nous sert à dire ceci: « Tous les contrôles dont le nom commencera par le préfixe
indiqué, correspondront à des types se trouvant dans l’espace de nom spécifié ».

Thomas LEBRUN
[Link] 55
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

A partir de là, il ne vous reste plus qu’à ajouter vos contrôles et vous disposez de deux
méthodes pour cela.
Première méthode, en utilisant du code XAML :

<Window x:Class="DemosWindowsFormsHost.Window1"
xmlns=[Link]
xmlns:x="[Link]
xmlns:wfi="clr-
namespace:[Link];assembly=WindowsFormsInteg
ration"
xmlns:wf="clr-
namespace:[Link];assembly=[Link]"
xmlns:s="clr-namespace:System;assembly=mscorlib"
>
<Grid>
<[Link]>
<RowDefinition Height="0.4*" />
<RowDefinition Height="0.6*" />
</[Link]>

<Label Content="Ceci est un Label WPF !"


HorizontalAlignment="Center" VerticalAlignment="Center" [Link]="0"
/>
<Grid [Link]="1">
<wfi:WindowsFormsHost>
<wf:ListBox>
<wf:[Link]>
<s:String>ListBox WindowsForms
!</s:String>
<s:String>C'est cool</s:String>
</wf:[Link]>
</wf:ListBox>
</wfi:WindowsFormsHost>
</Grid>
</Grid>
</Window>

Deuxième méthode, en utilisant du code .NET (C#, [Link], etc…) :

private void WindowLoaded(object sender, RoutedEventArgs e)


{
WindowsFormsHost host = new WindowsFormsHost();

[Link] lb = new
[Link]();
[Link]("ListBox WindowsForms !");
[Link]("C'est cool");
[Link](lb);

[Link](host);
}

Ces codes sont suffisament parlant, je ne vais donc pas m’attarder sur leur description car je
préfère vous parler des avantages et inconvénients de l’utilisation de WindowsFormsHost.

Thomas LEBRUN
[Link] 56
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Le gros avantage apporté par la première technique est qu’elle fournit un support complet du
XAML. Cependant, il y a deux inconvénients :
o les contrôles doivent avoir un constructeur par défaut
o il est impossible de définir, via le code XAML, les sous-propriétés. Il faut
passer par le code.

Note : Si, à la compilation de votre projet, vous avez une erreur à propos de la sérialisation, et
que vous utilisez la CTP de Février de Crossbow, essayez de remplacer la référence vers la
DLL [Link] par celle se trouvant ici :

C:\Program Files\Microsoft Visual


Studio8\Common7\IDE\Cider\[Link]

Voici une capture d’écran de ce que vous pouvez obtenir avec, à gauche, une ListBox
WindowsForms et en haut et à droite, un label et un bouton WPF :

Malgré la « jeunesse » du projet, on peut voir que pas mal de travail a été réalisé car, même si
l’application que je vous montre est très sobre, rien ne vous empêche de faire des choses
beaucoup plus complexes.
On regrettera toutefois qu’il ne soit pas possible d’utiliser de RenderTransform ni même
d’animations.

Pour finir, nous allons maintenant vois comment intégrer un contrôle WPF dans une
application WindowsForms.

Là encore, pas de mystère : il va y avoir plusieurs étapes et la première concerne, une fois de
plus, l’ajout des références nécessaires.
Ces références sont les suivantes :
o PresentationCore,
o PresentationFramework,
o WindowsBase,
o UIAutomationTypes,
o UIAutomationProvider,

Thomas LEBRUN
[Link] 57
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Elles se situent dans le répertoire C:\Program Files\Reference


Assemblies\Microsoft\WinFx\v3.0 (là encore, le numéro de version dépend de la version
BETA de WinFX que vous utilisez).
Dernière référence à ajouter : WindowsFormsIntegration.

Maintenant que les références nécessaires sont ajoutées, il ne vous reste plus qu’à développer
vos pages (ou contrôles) WPF et à les intégrer dans votre application WindowsForms, grâce à
l’ElementHost.
Voici une première démonstration, simple :

private void Form1_Load(object sender, EventArgs e)


{
[Link] host = new
[Link]();

[Link] = [Link];
[Link] button = new
[Link]();
[Link] = "Boutton Windows Presentation Foundation";
[Link] =
[Link];
[Link] =
[Link];

[Link](button);

[Link](host);

[Link] += delegate { [Link]++; };


}

Comme vous pouvez le voir, on déclare un ElementHost, puis un bouton WPF.


Ensuite, on ajoute notre bouton à notre contrôle de regroupement (l’ElementHost) puis on
ajoute ce contrôle de regroupement à la collection de contrôle de notre formulaire.
La dernière ligne a été rajoutée pour éviter un bug de la CTP de Février de Crossbow : rien
n’apparait à l’écran si vous ne modifiez pas la taille de la fenêtre, à l’exécution. Du coup,

Thomas LEBRUN
[Link] 58
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

cette ligne permet d’incrémenter la taille, sans que cela soit visible à l’utilisateur, et sans qu’il
se rendre compte de ce problème.

Le résultat de cette démonstration est visible sur cette photo :

Vous aurez sans doute du mal à le voir, mais le bouton du haut est bien un contrôle
WindowsForms « classique », tandis que le contrôle du bas est un bouton WPF.

Bien entendu, vous n’êtes pas limité à l’ajout de simples contrôles sur votre formulaire : vous
pouvez tout à fait rajouter des contrôles utilisateurs, des pages, etc…
Voyons cela un peu plus en détails, pour pouvoir conclure ce chapitre.

Imaginez par exemple que vous disposez de ce contrôle utilisateur, développé en XAML :

<UserControl x:Class="[Link]"
xmlns="[Link]
xmlns:x="[Link]

<Grid>
<[Link]>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</[Link]>

<ListView [Link]="0">
<ListViewItem> 1er élément </ListViewItem>
<ListViewItem> 2ème élément </ListViewItem>
<ListViewItem> 3ème élément </ListViewItem>
</ListView>

<TextBlock [Link]="1">
TextBlock WPF :)
</TextBlock>

<ComboBox [Link]="2" Height="150" Width="150"


VerticalAlignment="Center" HorizontalAlignment="Center">
<ComboBoxItem> 1er Item </ComboBoxItem>
<ComboBoxItem> 2ème Item </ComboBoxItem>
<ComboBoxItem> 3ème Item </ComboBoxItem>
</ComboBox>
/Grid>
</UserControl>

Thomas LEBRUN
[Link] 59
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

Ici, rien de bien extraordinaire : notre UserControl est composé d’une ListView, d’un
TextBlock et pour finir, d’une ComboBox, le tout regroupé dans une Grid.

Maintenant, il faut utiliser un ElementHost pour intégrer notre UserControl sur notre
formulaire Windows :

using [Link];

ElementHost host2 = new ElementHost();


[Link] = [Link];

MyWPFUserControl ctrl = new MyWPFUserControl();


[Link](ctrl);

[Link](host2);

[Link] += delegate { [Link]++; };

Là encore, rien de nouveau : on créé une instance d’un nouvel ElementHost, puis on y ajoute
une nouvelle instance de notre contrôle utilisateur.
On ajoute ensuite notre instance d’ElementHost à notre formulaire et, à l’exécution de
l’application, vous vous rendez compte que votre contrôle n’apparait pas à l’écran (vous
devriez même avoir une erreur de compilation, à propos de la méthode InitializeComponents
de votre UserControl).

En effet, dans sa version actuelle (Crossbow étant toujours un produit en version BETA) ; il y
a une petite manipulation à faire sur le fichier de projet de votre application (.csproj ou
.vbproj) avant que cela ne fonctionne correctement. Avant de vous donner la solution, je vais
vous expliquer pourquoi vous obtenez cette erreur.

Lorsque vous développez une application WPF, le compilateur sait comment il doit parser le
XAML, créer sa représentation binaire (c’est ce que l’on appelle le BAML) et générer le code
correspondant.

Cependant, ici, nous développons une application WindowsForms et le modèle qui a été
utilisé pour créer cette application WPF ne connait rien du tout au XAML.

Nous allons donc devoir enseigner, à notre application WindowsForms, à comprendre ce


fichier XAML et faire ce qu’il convient de faire.

Pour cela, éditez le fichier de projet et recherchez la ligne :

Thomas LEBRUN
[Link] 60
Windows Presentation Foundation :
La nouvelle génération d’interfaces graphiques

<Import Project="$(MSBuildBinPath)\[Link]" />

Ou la ligne, suivant le type de projet que vous avez créez:

<Import Project="$(MSBuildBinPath)\[Link]" />

Puis, rajoutez la ligne suivante juste après:

<Import Project="$(MSBuildBinPath)\[Link]" />

Grossièrement, cette ligne sert à indiquer, au système de compilation, comment générer des
applications WinFX.
Vous indiquez donc que la cible de votre compilation est un assemblage WinFX.

Le résultat est visible sur cette capture d’écran :

Nous avons donc toujours nous deux boutons.


Sur la partie de gauche, nous avons des contrôles WindowsForms et sur la droite, nous avons
les mêmes types de contrôles, mais en version WPF (et intégré dans un UserControl WPF).

Ainsi, même si la technologie Crossbow est encore jeune, elle semble vraiment avancée et
permet de réaliser, de façon assez simple et rapide, des applications mêlant à la fois WPF et
WindowsForms.

7. Conclusions :
Au travers de cet article, j’ai essayé de couvrir un maximum de choses sur Windows
Presentation Foundation.
Bien sur, il y aurait beaucoup à rajouter et/ou à compléter.

Cependant, vous avez dorénavant les bases suffisantes pour commencer à développer,
aujourd’hui, les applications que nous utiliserons demain !

Thomas LEBRUN
[Link] 61

Vous aimerez peut-être aussi