根据 light/dark 主题在运行时切换 XAML 资源?

Switch XAML resources at runtime based on light/dark theme?

我有一个使用 MahApps(“轻”模式)的 WPF 应用程序,我现在为用户提供了一种切换模式的方法 (light/dark)。许多应用程序的颜色明显根据模式而变化,通过比较 \Styles\Themes\Light.colour_name.xaml 和 Dark 可以看出。 colour_name.xaml 文件,但我想通过实现我自己的 xaml <Color> 资源以某种方式“扩展”这些文件这也会根据所选模式而改变。这能做到吗?

一个示例是当前使用蓝色绘制点的图表 - 这些图表在“浅色”模式下看起来不错,但在“深色”模式下有点暗。我意识到我可以使用更合适的蓝色阴影,它在两种模式下看起来都不错,但如果我可以定义一个 Color 资源,它会更灵活(比如)在灯光模式下 'Blue' 但 'Lime' 在深色模式下。这种功能也可能有其他用途,例如彩色通知消息。

您可以根据 built-in 主题创建自定义主题。创建一个资源字典,合并基础主题的资源字典并覆盖现有画笔并添加新画笔。

浅色主题词典(Light.Blue.Custom.xaml):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" >
   <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
   </ResourceDictionary.MergedDictionaries>

   <!-- Overriding default brushes -->
   <SolidColorBrush x:Key="MahApps.Brushes.Button.Border.MouseOver" Color="Blue" options:Freeze="True" />

   <!-- Adding your own brushes -->
   <SolidColorBrush x:Key="My.Brushes.Notification.Alert" Color="Red" options:Freeze="True" />

</ResourceDictionary>

深色主题词典(Dark.Blue.Custom.xaml):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" >
   <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Dark.Blue.xaml" />
   </ResourceDictionary.MergedDictionaries>

   <!-- Overriding default brushes -->
   <SolidColorBrush x:Key="MahApps.Brushes.Button.Border.MouseOver" Color="DarkBlue" options:Freeze="True" />

   <!-- Adding your own brushes -->
   <SolidColorBrush x:Key="My.Brushes.Notification.Alert" Color="DarkRed" options:Freeze="True" />

</ResourceDictionary>

在您的应用程序中注册主题词典。您 必须在 class 和资源字典 URI 中用您的应用程序的真实名称替换 虚拟名称 YourApp

public partial class YourApp : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var lightBlueCustomTheme = ThemeManager.Current.AddLibraryTheme(new LibraryTheme(
            new Uri("pack://application:,,,/YourApp;component/Light.Blue.Custom.xaml"),
            MahAppsLibraryThemeProvider.DefaultInstance));

        var darkBlueCustomTheme = ThemeManager.Current.AddLibraryTheme(new LibraryTheme(
            new Uri("pack://application:,,,/YourApp;component/Dark.Blue.Custom.xaml"),
            MahAppsLibraryThemeProvider.DefaultInstance));

        ThemeManager.Current.ChangeTheme(this, lightBlueCustomTheme);
        
        // Optionally enable App Mode theme switching
        // ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncWithAppMode;
        // ThemeManager.Current.SyncTheme();
    }
}

请注意,您需要为 both LightDark 提供主题,如果您想切换模式。有关主题和自定义的更多信息,您可以参考 documentation.