Dans mon post précédent, j’ai fait part d’une solution pour localiser vos applications sans passer par l’outil LocBaml. J’utilisais des ResourceDictionary que j’affectais dynamiquement au moment de l’exécution. Cette méthode peut être utilisée dans plusieurs cas, et l’une d’entre elle : les thèmes.
Devoir gérer plusieurs thèmes dans les applications était auparavant un travail assez complexe (je pense à la création de contrôle personnalisée, que la technologie WPF nous a permis de faire beaucoup plus simplement), mais maintenant avec les ResourceDictionary, c’est devenu relativement “simple”. Bien sûr, ceci n’est qu’un exemple d’application et il reste assez basique à mettre en place, mais cela pourra vous inspirer.
Nous allons créer deux thèmes : “default” et “light”. Pour cela, comme expliquer ci-dessus, nous allons ajouter des ResourceDictionary (dictionnaire de ressources en français) :
Maintenant, nous allons remplir ces fichiers :
<!-- Default.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<System:String x:Key="ThemeName">Default</System:String>
<SolidColorBrush x:Key="win_background" Color="DarkBlue"></SolidColorBrush>
<Style TargetType="Button">
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="FontSize" Value="10px"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="LightBlue" />
</Style>
</ResourceDictionary>
<!-- Light.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<System:String x:Key="ThemeName">Light</System:String>
<SolidColorBrush x:Key="win_background" Color="LightBlue"></SolidColorBrush>
<Style TargetType="Button">
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="FontSize" Value="10px"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Background" Value="White" />
</Style>
</ResourceDictionary>
Puis la déclaration dans le point d’entrée de l’application du thème par défaut :
<Application x:Class="WPFThemes.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes\Default.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Maintenant que tout cela est fait, on va implémenter la méthode qui va nous permettre de changer de thème dynamiquement dans le point d’entrée de notre application :
public partial class App : Application
{
private ResourceDictionary obj;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
foreach (ResourceDictionary item in this.Resources.MergedDictionaries)
{
if (item.Source != null && item.Source.OriginalString.Contains(@"Themes\"))
{
obj = item;
}
}
}
public void ChangeTheme(Uri dictionnaryUri)
{
if (String.IsNullOrEmpty(dictionnaryUri.OriginalString) == false)
{
ResourceDictionary objNewLanguageDictionary =
(ResourceDictionary)(LoadComponent(dictionnaryUri));
if (objNewLanguageDictionary != null)
{
this.Resources.MergedDictionaries.Remove(obj);
this.Resources.MergedDictionaries.Add(objNewLanguageDictionary);
}
}
}
}
Il faut savoir que quand on utilise beaucoup de ResourceDictionary, il peut se produire un impact négatif sur les performances : ce sera mon prochain article :).
Maintenant pour pouvoir lié notre interface avec les styles :
<Window x:Class="WPFThemes.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Background="{DynamicResource ResourceKey=win_background}">
<Grid>
<Button Content="Changer le thème" Height="51" HorizontalAlignment="Center"
Name="btnChangeTheme" VerticalAlignment="Center" Width="110"
Click="btnChangeTheme_Click" />
</Grid>
</Window>
Pour télécharger les sources, ici.
A bientôt !