在 Avalonia 中实现亮暗模式切换,核心是动态替换
Styles中的资源字典(特别是颜色、画刷等主题变量),并配合系统监听或手动触发更新。它不依赖 WPF 那套 ThemeManager,而是靠手动管理
App.Styles或窗口级
Styles的加载与替换。
1. 准备两套主题资源字典
创建两个
ResourceDictionaryXAML 文件,分别定义亮色(Light)和暗色(Dark)主题的颜色资源:
Themes/Light.xaml:包含
Brush、
Color、
Thickness等基础资源,如
ThemeBackgroundBrush设为
#FFFFFF
Themes/Dark.xaml:对应设为
#1E1E1E、
#333等暗色值
确保每个资源都有唯一
x:Key,且类型一致(比如都用
SolidColorBrush),方便运行时替换。
2. 在 App.axaml 中动态加载主题
不要直接在
App.axaml的
Styles里静态引用主题文件。改为在
App.OnFrameworkInitializationCompleted()中按需加载:
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// 初始加载亮色主题
LoadTheme("Light");
desktop.MainWindow = new MainWindow();
desktop.MainWindow.Show();
}
base.OnFrameworkInitializationCompleted();
}
private void LoadTheme(string themeName)
{
var app = Application.Current;
app.Styles.Clear();
// 加载基础样式(如 DefaultTheme.xaml)
app.Styles.Add(new StyleInclude(new Uri("resm:Avalonia.Themes.Default?assembly=Avalonia.Themes.Default")));
// 加载当前主题
var themeUri = new Uri($"resm:YourApp.Themes.{themeName}.xaml?assembly=YourApp");
app.Styles.Add(new StyleInclude(themeUri));
}
3. 提供切换方法并通知 UI 更新
切换主题只需重新调用
LoadTheme("Dark") 或 LoadTheme("Light") 即可。Avalonia 会自动刷新所有绑定到这些资源的控件(前提是使用 {DynamicResource KeyName} 而非 {StaticResource})。
在 ViewModel 或菜单中添加切换命令,例如:RelayCommand SwitchThemeCommand => new(() => LoadTheme(UseDarkTheme ? "Light" : "Dark"));用
Application.Current.RequestedTheme可选地同步系统偏好(仅 Avalonia 11+ 支持),但建议以手动控制为主,更可控 避免在
MainWindow构造函数里硬编码主题,所有样式应由
App.Styles统一管理
4. 前端使用 DynamicResource 绑定
在 XAML 中必须用
{DynamicResource} 引用主题资源,否则切换后不会更新:
<Border Background="{DynamicResource ThemeBackgroundBrush}">
<TextBlock Foreground="{DynamicResource ThemeForegroundBrush}" Text="Hello"/>
</Border>
静态资源(
{StaticResource})只在加载时解析一次,无法响应后续替换;而 DynamicResource会持续监听资源变化。
基本上就这些。不复杂但容易忽略的是资源键名一致性、DynamicResource 的使用,以及清空并重装 Styles 的时机。只要资源结构清晰、切换逻辑干净,亮暗模式就能平滑生效。
