Proper way to switch Dark/Light theme #5347
-
Here's what I'm currently doing for switching themes: public class ThemeManager
{
private const string DARKTHEMENAME = "BaseDark";
private const string LIGHTTHEMENAME = "BaseLight";
private static StyleInclude GenerateDarkTheme()
{
return new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri($"avares://Avalonia.Themes.Default/Accents/{DARKTHEMENAME}.xaml")
};
}
private static StyleInclude GenerateLightTheme()
{
return new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri($"avares://Avalonia.Themes.Default/Accents/{LIGHTTHEMENAME}.xaml")
};
}
private static ThemeManager instance;
public static ThemeManager Instance
{
get
{
if (instance == null)
{
instance = new ThemeManager();
}
return instance;
}
set
{
instance = value;
}
}
private List<AvaloniaObject> monitoredObjects = new List<AvaloniaObject>();
public ThemeManager()
{
Settings.OnSettingsUpdated += UpdateAllThemes;
}
public void MonitorTheme(Window window)
{
monitoredObjects.Add(window);
ModifyStyles(window.Styles);
}
public void MonitorTheme(Application application)
{
monitoredObjects.Add(application);
ModifyStyles(application.Styles);
}
private void UpdateAllThemes()
{
foreach (AvaloniaObject obj in monitoredObjects)
{
if (obj is Application app)
{
ModifyStyles(app.Styles);
}
else if (obj is Window window)
{
ModifyStyles(window.Styles);
}
}
}
private void ModifyStyles(Styles styles)
{
styles.RemoveAll(styles.Where(s => s is StyleInclude styleInclude && (styleInclude.Source.OriginalString.Contains(DARKTHEMENAME) || styleInclude.Source.OriginalString.Contains(LIGHTTHEMENAME))).ToList());
StyleInclude style = Settings.Instance.ApplicationTheme == ApplicationTheme.Dark ? GenerateDarkTheme() : GenerateLightTheme();
styles.Insert(0, style);
}
public void ToggleTheme()
{
switch (Settings.Instance.ApplicationTheme)
{
case ApplicationTheme.Light:
Settings.Instance.ApplicationTheme = ApplicationTheme.Dark;
break;
case ApplicationTheme.Dark:
Settings.Instance.ApplicationTheme = ApplicationTheme.Light;
break;
}
Settings.SaveSettings();
}
} And the App & Windows call |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
With the new Fluent theme you can just simply do: |
Beta Was this translation helpful? Give feedback.
-
Yeah, switching themes needs to be finished off - you can do it currently but as others have said it's got a few glitches. Now that 0.10 is out hopefully we can get this done in one of the upcoming 0.10.x releases. |
Beta Was this translation helpful? Give feedback.
-
Do you know if it's possible to create a dark and light theme by hand, I'm thinking of a dictionary that could vary dynamically according to a toggleswitch? Without using RequestedThemeVariant |
Beta Was this translation helpful? Give feedback.
With the new Fluent theme you can just simply do:
new FluentTheme { Mode = FluentThemeMode.Dark }
instead of manually including the URI. Unfortunately this only works with fluent and not the default theme.I think you only need to update the styles on the
Application
not the windows, that should already be enough. Although switching themes at runtime is sometimes a bit cumbersome. I ended up restarting the window to have everything update correctly (Not sure if there's a ticket for this somewhere).