mercredi 27 juin 2012

Gestion des thèmes dans un projet .net

Suite à l'article de gestion des ressources, nous verrons aujourd'hui la gestion des thèmes dans un projet .Net.

Un thème ?

Un thème est un ensemble de ressources (images, style, ...). Cet ensemble d'information se trouve dans un sous-répertoire du répertoire "App_Themes" de notre solution. Le nom de ce sous-répertoire définit le nom de notre thème.
Une fois cette architecture respectée, le thème peut contenir autant de répertoire et fichier souhaité, sans contrainte particulière.

Appliquer un thème

Pour cela, il existe plusieurs solutions.

Nous pouvons définir un thème global pour l'application. Pour cela, il suffit de définir dans le fichier de configuration (le web.config pour un site asp.net) le nom du thème à appliquer, au niveau de l'entrée "pages".


Le thème peut aussi être défini pour chaque page. Pour cela, il faut le définir dans l'en-tête de notre template aspx ou ascx. Cette définition surcharge celle faite dans le "web.config".

La dernière solution est de l'appliquer au runtime. Encore une fois, cette solution surcharge les deux précédente :

Attention : contrairement à ce que j'ai écrit dans le screen, l'affectation du thème doit se faire lors du PreInit de la page (plus d'info ici).

Utilisation du thème

Lorsque l'on applique un thème, chaque fichier ".css" inclus dans le dossier est automatiquement appliqué à la page. C'est cool : pas besoin de penser aux références :)
Cependant pour les images, c'est une autre paire de manche...

On ne peut pas utiliser les images avec les chemins relatifs habituels (~/Images/trug.png), ou sinon on inclut le nom du thème dans le chemin. Et à ce moment là, quel intérêt d'utiliser un thème ?

On a alors deux solutions :

  • Référencer chaque appel d'une image en code-behind, en utilisant le thème en cours (Page.Theme)
  • Utiliser un fichier ".skin"

Met un skin dans ton thème !


Dans notre fichier ".skin", on définit les images utilisables : 
Le SkinID n'est pas nécessairement unique dans un fichier, mais il est unique par contrôle (dans notre cas Image et ImageButton).
Et les images utilisées sont évidement dans notre répertoire de thème, on peut alors avoir des images différentes par thème, tant que les SkinID sont identique.
On peut aussi référencer des images qui ne sont pas dépendantes de skin ! Bref, la vie est belle :)

On utilise ensuite notre Skin dans les templates aspx, ascx  tel que : 
Et voila.




dimanche 17 juin 2012

Gestion des ressources dans un projet .NET

Gestion des ressources dans une application


Une ressource ?

Les ressources sont l'ensemble des textes, images, élément affichable qui peuvent être affiché dans une application. Cette dernière peut être un site web, une application WPF, WindowsPhone... les fichiers de ressources peuvent être partagés entre ces divers projets.

.resx

Un fichier de ressource est un fichier ".resx", un fichier XML qui défini pour chaque ressource, une balise "data" avec deux attributs et au moins un élément fils :

  • un attribut "name" qui définit la clé pour appeler la ressource.
  • un attribut "xml:space" qui prend la valeur "preserve" lorsque la ressource est créée par l'éditeur. Les espaces présents dans la donnée en rapport avec cette ressource seront concervés. En la définissant à "default", ou en ne la définissant pas, les espaces seront ignorés. 
  • un élément fils "value" qui définit la valeur à afficher lorsque la clé sera appliquée dans le code
  • un élément optionnel "comment" pour y placer un commentaire à destination du développeur.
Exemple :


<data name="AppName" xml:space="preserve">
    <value>POME</value>
    <comment>Application name</comment>
  </data>

Attention cependant : en utilisant le lecteur de ressource par défaut de Visual Studio, les ressources du fichier XML sont triés. Cette modification du fichier .resx, à chacune des ouvertures, va rendre complexe le merge de branche, lorsque l'on travaille avec des outils (indispensables!) de versionning tel que TFS ou SVN.
Pour ma part, je les ouvre donc avec l'éditeur XML :

Clic droit -> Ouvrir avec -> Editeur XML (Texte) avec encodage. Sélectionner "Par défaut", puis valider.


Modifier le lecteur de ressource par défaut

Ce fichier ".resx" peut être créé en plusieurs endroits :

  • Dans un répertoire placé à la racine, nommé "App_GlobalResources". Les fichiers de ressources définis dans ce répertoire seront accessibles partout dans l'application. Cela peut être le bon endroit pour y définir les valeurs de "Oui", "Non", "Valider", ... Tous ces mots courants qui se retrouveront dans toute l'application.
  • Dans un répertoire "App_LocalResources" placé au niveau d'un template : une page ".aspx" ou un composant ".ascx" pour un site ASP.NET, une page ou un composant ".xaml" pour un projet Silverlight ou WP7. Les ressources ne seront définies que localement au template.
  • Ou bien n'importe où ! Et oui, un fichier de ressource peut être défini et utilisé depuis un projet différent. Cela casse cependant le processus de binding, automatiquement mis en place par les répertoires prévus à cet effet. 

Mécanismes

Le premier mécanisme est la possibilité d'appliquer un outil personnalisé ("CustomTool") à un fichier de ressource. Cet outil est une classe qui permettra de générer automatiquement un Designer associé à un fichier de ressource. Ce designer est en fait une classe C# qui reprend automatiquement l'ensemble des ressources du fichier afin de les exposer sous forme de propriété statique. Elles seront alors facilement utilisables via notre code C#.
Pour appliquer cet outil à un fichier de ressources : cliquer droit sur le fichier, propriété, puis y ajouter le nom de l'outil dans le champs correspondant (exemple d'outil : "GlobalResourceProxyGenerator" ou "ResXFileCodeGenerator"). Il est possible de créer son propre outils, mais cela demande de créer une COM classe et de l'enregistrer dans le registre du poste du développeur... pas très pratique !

Pour reprendre notre exemple de tout à l'heure, où notre fichier de ressources dans App_GlobalResources, nommé "Global" définit une ressource "AppName" et notre fichier dans App_LocalResources définit une ressource "Example" :  
Utilisation des ressources en code-behind
Attention : il est important de tester l’existence de la ressource dans un fichier qui n'a pas de Designer associé. Il n'y a pas de ressource par défaut renvoyée, une exception serait alors déclenchée.

L'équivalent pour afficher ces ressources dans des templates d'un site ASP.NET : 
Utilisation des ressources dans les templates

Ici, une ressource inexistante n’empêchera pas non plus la compilation, mais il y aura une erreur à l'exécution.


Quel utilité?

Si vous êtes arrivé jusqu'ici sans vous demander pourquoi mettre en place tout ce processus pour afficher juste des chaînes de caractères, il y a un souci ! En effet, c'est plutôt contraignant, donc pourquoi se donner cette peine ?

Réponse : pour se simplifier la localisation de votre application,  pouvoir changer les textes et les images affichés en fonction de la langue.
Pour cela, il suffit de définir des fichiers de ressources pour chaque langue que l'on souhaite supporter. Les nom des fichiers ont une importance particulière : ils définissent à quel langue correspond tel fichier.
Ex : 
Exemple de fichiers de ressources

En définissant ces 4 fichiers, nous supportons à présent plusieurs langues : 
  • L'anglais (en)
  • Le français (fr)
  • Le français, spécifiquement pour la Belgique (fr-BE)
Chaque fichier re-définit tout ou partie des clés définies dans le fichier initial "Global.resx". Si une clé n'est pas définie dans le langage spécifique, alors le fichier de ressources du langage parent (ex : fr, pour le fr-BE) est interrogé. Encore une fois, si la clé n'est pas définie pour un langage, le fichier de défaut sera interrogé. Une exception sera déclenchée si la clé est appelée mais n'est pas définie.


La langue utilisée par votre application est définie par :
Thread.CurrentThread.CurrentUICulture

Cette valeur est assignable tel que : 
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1033);

Le paramètre passé à CultureInfo est le LCID de la langue. La liste des LCID pour chaque langage est disponible ici :  http://msdn.microsoft.com/en-us/goglobal/bb964664

Pour plus d'informations, msdn regorge de fiches à ce propos : http://msdn.microsoft.com/fr-fr/library/ms247246(v=vs.80).aspx