Setting Theme/Accent with MahApps.Metro

I’m building up a sample app that leverages the MahApps.Metro libraries.  One of the challenges is setting the AppTheme and Accent colors dynamically.   I looked through more than a few online solutions and none of them worked for me.  Usually, the syntax was from an earlier version and didn’t match the ThemeManager object that I downloaded from NuGet (v1.0.0.0).

After comparing the sample app (v4.5) against my code in VS, I noticed the results from ThemeManager.DetectAppStyle() was always null in my app and valid in the sample app.  I figured I set something up wrong, but I never did figure out exactly what I was missing.  Instead of wasting another day on this, I decided to force the two values to what I wanted.

Aside: This might be a case where the NuGet package isn’t 100% synchronized with the latest source.  Not that it helps me solve my problem.  I’m fairly new to using NuGet.  All of my previous attempts have run into serious versioning problems.  That’s a topic for another day.

Here’s what I did to ‘hack’ around the problem.

The first thing was to add settings to the shell project.  I added AppThemeName and AccentName.

Capture

Then I created a wrapper class to make managing the settings easier.

[code lang=”csharp”]
using MahApps.Metro;

namespace Module.Ux.Models
{

public class ThemeSettings
{

public AppTheme AppTheme { get; set; }
public Accent Accent { get; set; }

public static ThemeSettings Load()
{
var appTheme = ThemeManager.GetAppTheme(Properties.Settings.Default.AppThemeName);
var accent = ThemeManager.GetAccent(Properties.Settings.Default.AccentName);
var settings = new ThemeSettings
{
Accent = accent,
AppTheme = appTheme,
};
return settings;
}

public void Save()
{
Properties.Settings.Default.AccentName = Accent.Name;
Properties.Settings.Default.AppThemeName = AppTheme.Name;
Properties.Settings.Default.Save();
}

}

}
[/code]

The next part is changing  the DoChangeTheme() methods in both helper classes.   I swiped these from the Samples provided with the source code.  I also had to copy over the SimpleCommand class.  I’ll refactor it out when I have more time.  All three of these classes are in the MainWindowViewModel.cs file in the MetroDemo.NET45 sample app.  Below is my updated versions:

[code lang=”csharp”]
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using MahApps.Metro;

namespace Module.Ux.Models
{

public class AccentColorMenuData
{

// ReSharper disable once InconsistentNaming
internal ThemeSettings settings;

private ICommand changeAccentCommand;
public ICommand ChangeAccentCommand
{
get { return changeAccentCommand ?? ( changeAccentCommand = new SimpleCommand { CanExecuteDelegate = x => true, ExecuteDelegate = x => DoChangeTheme(x) } ); }
}

public string Name { get; set; }
public Brush BorderColorBrush { get; set; }
public Brush ColorBrush { get; set; }

protected virtual void DoChangeTheme(object sender)
{
if ( settings == null )
settings = ThemeSettings.Load();

settings.Accent = ThemeManager.GetAccent(Name);
ThemeManager.ChangeAppStyle(Application.Current, settings.Accent, settings.AppTheme);
settings.Save();

}

}

}
[/code]

[code lang=”csharp”]
using System.Windows;
using MahApps.Metro;

namespace Module.Ux.Models
{

public class AppThemeMenuData : AccentColorMenuData
{

protected override void DoChangeTheme(object sender)
{

if ( settings == null )
settings = ThemeSettings.Load();

settings.AppTheme = ThemeManager.GetAppTheme(Name);
ThemeManager.ChangeAppStyle(Application.Current, settings.Accent, settings.AppTheme);
settings.Save();

}

}

}
[/code]

Works on my machine.

References: