Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Thomas Lebrun

Tout sur WPF, LINQ, C# et .NET en général !

Actualités

[WPF] Style et Template: Ou comment faire pour séparer la logique métier du code de présentation

L'un des grands avantages de WPF (Windows Presentation Foundation) est qu'il permet aux développeurs et aux designers de travailler conjointement sur un projet sans que l'un d'entre eux ait besoin d'attendre qu'un autre finisse son travail pour pouvoir avancer Smile

Cette technique de travail peut, aux premiers abords, paraitre déroutante car elle n'a rien à voir avec ce que l'on fait au jour d'aujourd'hui. Mais au final, elle se révèle très performante et nous allons tenter de bien comprendre pourquoi et comment fonctionne ce mécanisme de travail développeur-designer.

Il y a 2 façons d'aborder un développement WPF:

  • La première consiste à partir du principe que c'est le designer qui va mener le projet. A ce titre, c'est lui qui sera en charge de réaliser une maquette de toute l'interface graphique et le développeur n'aura plus qu'a récupérer cette ébauche pour commencer son développement.
  • L'autre technique consite à partir du principe que c'est le développeur qui sera le meneur du projet. Il sera donc en charge d'esquisser une interface graphique sommaire mais qui suffira à ces besoins et le désigner n'aura plus qu'a travailler sur cette esquisse pour produire un rendu final correct.

Dans les 2 cas, le développeurs et le designer devront régulièrement fusionner leur travaux afin de commencer à produire l'application finale.

Mais comment est-ce possible ? Comment un développeur peut-il travailler sur une application WPF, alors que son design n'est pas encore fait/terminé ?

La réponse est simple et tiens en 2 mots: style et template Smile

Pour rappel, les styles correspondent, pour simplifier, à toute la partie "visuelle" des contrôles (couleur d'arrière-plan, couleur de la police, style de la police, etc...) et les templates, quand à eux, sont utilisé pour modifier la façon dont les contrôles sont affichés à l'écran. C'est grâce à eux que vous allez pouvoir dire que vous voulez que votre bouton ne soit plus un rectangle mais devienne un cercle ou ce que vous voulez d'ailleurs Wink

Ainsi, lors de la création du projet, une ébauche est établie:

<Window x:Class="TestItemsControl.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="TestItemsControl" Height="300" Width="300"

    >

  <StackPanel Orientation="Vertical">

    <TextBox x:Name="tb" />

    <Button Content="Change" x:Name="btn" Click="ChangeClick" />

  </StackPanel>

</Window>

Et le groupe de travail se sépare avec chacun (développeurs et designers) une copie de cette ébauche sur laquelle il vont travailler "localement".

Les développeurs ajouteront toute la logique métier de l'application (connexion à une base de données, utilisation de Web Services, etc....) tandis que les designers travailleront de leur coté pour produire les objets de type Brushes, Path, Style, Template, etc.... (exportés dans des ResourceDictionary) qui seront nécessaires à l'élaboration de l'interface finale.

Lors de leurs rencontres, développeurs et designers devront fusionner leur travaux. Cela peut-être fait par l'un ou l'autre mais on voit apparaitre, de plus en plus, le métier d'intégrateur WPF. Son rôle (comme vous pouvez vous en doutez) sera d'intégrer/de fusionner le travail des 2 parties pour fournir l'application finale.

Cet intégrateur, qui possède à la fois des compétences de développeur et des compétences de designer, devra donc fusionner les ResourceDictionary fournit par les designers et les utiliser au sein de l'application:

  • Templates.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    >

  <ControlTemplate TargetType="{x:Type TextBox}" x:Key="tbTemplate">

    <Grid x:Name="Grid">

      <Border x:Name="Border" Background="Transparent" BorderBrush="Gray" BorderThickness="1" Padding="2" CornerRadius="2">

        <ScrollViewer

                  Margin="0"

                  x:Name="PART_ContentHost"

                  Background="{TemplateBinding Background}"

                  Width="{TemplateBinding Width}"

                  Height="{TemplateBinding Height}"

                  BorderThickness="{TemplateBinding BorderThickness}"

                  HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"

                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"

                  Foreground="{TemplateBinding Foreground}"

                />

      </Border>

    </Grid>

  </ControlTemplate>

</ResourceDictionary>

  • Window1.xaml:

<Window x:Class="TestItemsControl.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="TestItemsControl" Height="300" Width="300"

    >

  <Window.Resources>

    <ResourceDictionary>

      <ResourceDictionary.MergedDictionaries>

        <ResourceDictionary Source="Templates.xaml" />

      </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>

  </Window.Resources>

 

  <StackPanel Orientation="Vertical">

    <TextBox x:Name="tb" Template="{StaticResource tbTemplate}" />

    <Button Content="Change" x:Name="btn" Click="ChangeClick" />

  </StackPanel>

</Window>

Comme vous pouvez le constatez, utiliser les ResourceDictionary est assez simple: il suffit d'utiliser la collection MergedDictionaries pour ajouter les ResourceDictionary auxquels on souhaite avoir accès dans notre projets:

<ResourceDictionary>

    <ResourceDictionary.MergedDictionaries>

        <ResourceDictionary Source="Templates.xaml" />

    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

Pour pouvoir appliquer le style/template, il suffit ensuite de l'appeler:

<TextBox x:Name="tb" Template="{StaticResource tbTemplate}" />

Maintenant, le plus gros du travail est fait: si un designer modifie un style ou un template, l'intégrateur n'aura qu'a remplacer le fichier XAML (ou juste les parties modifiées) et ne touchera plus au code (XAML et C#/VB.NET) de l'application.

Si vous êtes purement développeur et que vous développez vous-même vos propres styles/templates, sachez qu'il existe une technique qui vous permettra de les réutiliser sans avoir besoin de les réécrire. Frédéric Queudret, architecte au MTC Paris (Microsoft Technology Center), en a d'ailleurs fait une belle présentation sur son blog:

Externalisation des styles WPF en assembly satellite

La technique est relativement simple, facile à mettre en oeuvre et vous permettra de gagner pas mal de temps en terme de copier/coller Wink

A noter que cette technique peut également être appliquée au ResourceDictionary qui ont été créés par les designers mais ce sera plus le boulot de l'intégrateur (ou du développeur).

 

Voila, j'espère que cela vous sera utile :)

 

A+

 

del.icio.us tags:
 
Technorati tags:
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: mercredi 2 mai 2007 10:14 par Thomas LEBRUN
Classé sous : , ,

Commentaires

cyril a dit :

Question d'ignorant en WPF : comment cela se passe pour les animations ? Par exemple une image qui se change sur un mouseover rien que pour l'aspect graphique.

Le designer peut le faire tout seul ou c'est le travail du développeur ?  

# mai 2, 2007 19:13

Thomas LEBRUN a dit :

Cela peut-être fait par les 2 :)

Mais un designer ira certainement plus vite qu'un développeur. En effet, avec Blend, tout se passe avec la souris (et faire un MouseOver, c'est pas bien compliqué) alors que le développeur pourra faire la même chose, sans aucun problème, mais mettra plus de temps à écrire le code qu'il faut :)

De plus, on peut considérer qu'une opération de ce type, cela reste lié au design donc que cela revient au designer.

# mai 2, 2007 20:17

cyril a dit :

j'ai peut etre mal posé la question : bien sur que l'animation est lié au design.

Mais est-ce que le designer peut faire cette modif en touchant seulement le fichier templates.xaml ou alors doit on mettre l'animation dans le fichier window1.xaml qui est, d'aprés ce que je comprend, seulement pour le developpeur/intégrateur WPF ?

# mai 2, 2007 20:59

Thomas LEBRUN a dit :

templates.xaml, c'est une ResourceDictioniary donc une sorte de fichier qui sera inclut dans l'application afin "d'externaliser" certaines parties (styles, templates).

window1.xaml, c'est la partie "visuelle" de la page. Un peu comme en ASP.NET: tu as les fichiers aspx et les fichiers .aspx.cs (ou .vb).

Donc le designer pourra très bien déclarer l'animation dans un ResourceDictionary (donc templates.xaml). Par contre, lui ou le développeur/intégrateur devra modifier le fichier window1.xaml pour lui dire "d'appeller" l'animation au bon moment.

C'est plus clair ?

# mai 2, 2007 21:07

cyril a dit :

yes c'est plus clair : une animation peut donc être écrit dans le ResourceDictionary :)

# mai 2, 2007 21:26

Thomas LEBRUN a dit :

En effet: une animation, c'est un storyboard et un storyboard, ca se trouve dans les Resources donc ca peut très bien être dans un ResourceDictionary ;)

# mai 2, 2007 21:42

Matthieu MEZIL a dit :

Ah les templates ! Ou comment une super idée risque de provoquer des dérives avec des contrôles qui ne ressemblent plus à rien !

N'empêche que y a rien à dire c'est vraiment bien WPF mais le temps d'adaptation pour un développeur Winform n'est pas négligeable.

# mai 2, 2007 23:48
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Conf’SharePoint : 10 bonnes raisons pour ne pas la rater par Le petit blog de Pierre / Pierre's little blog le 05-14-2013, 02:24

- [Event] Soirée de lancement Agile .NET France à Lyon par Blog Agile/ALM de Vincent THAVONEKHAM le 05-13-2013, 01:29

- .NET / Debug : inspection de la mémoire d'applications .NET (dump ou processus live) : première livraison d'une librairie .NET par Microsoft par CoqBlog le 05-11-2013, 22:21

- SharePoint : Incompatibilité avec Internet Explorer 10 (IE10) par Blog Technique de Romelard Fabrice le 05-08-2013, 16:29

- AutoSPInstaller pour SharePoint 2013 maintenant disponible en “RTM” par Julien Chable le 05-06-2013, 23:30

- [TFS2010] A la recherche du Shelveset perdu par Blog de Jérémy Jeanson le 05-03-2013, 21:46

- .NET / Debug post-mortem : obtenir le fichier mscordacwks.dll correspondant à un dump quand on n'a plus d'accès direct à ce fichier par CoqBlog le 04-28-2013, 19:57

- [W8] Afficher un graphe par CPU dans le gestionnaire des tâches par Blog de Jérémy Jeanson le 04-28-2013, 17:48

- [WCF] Limiter proprement l’accès à vos ressources serveur par Blog de Jérémy Jeanson le 04-26-2013, 22:59

- Event : Je serai speaker à la Conf’SharePoint par Blog Technique de Romelard Fabrice le 04-26-2013, 12:00