WPF中切换主题功能

在现代 Windows 系统中,系统提供了亮色主题和暗色主题,Windows 自带的应用程序都已经适配该功能。本文介绍在使用 WPF 构建 Windows 窗口应用时怎么实现主题切换。

资源字典

在 WPF 中,资源是可在应用程序中的不同位置重复使用的对象,资源可以存储在 XAML 文件中,该文件称为资源字典文件,该文件没有配套的后端 cs 代码,使用纯粹的 xml 进行定义。在切换主题时,我们就需要用到资源文件。

颜色系统

首先,整理出整个应用的颜色系统,包含了边框颜色,背景颜色,主色,特殊色。如下所示:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <SolidColorBrush x:Key="BorderBrush" Color="#E5E5E5" />
    <SolidColorBrush x:Key="PageBackgroundBrush" Color="#F9F9F9" />
    <SolidColorBrush x:Key="PrimaryBrush" Color="#0D76F5" />
    <SolidColorBrush x:Key="DangerBrush" Color="#FF1214" />
</ResourceDictionary>

将文件保存为 Light.xaml,在同目录下再创建 Dark.xaml 文件,颜色字段与 Light.xaml 中一致,颜色值改成暗色主题相关即可。如下所示:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <SolidColorBrush x:Key="BorderBrush" Color="#4D4D4D" />
    <SolidColorBrush x:Key="PageBackgroundBrush" Color="#1C1C1F" />
    <SolidColorBrush x:Key="PrimaryBrush" Color="#0D76F5" />
    <SolidColorBrush x:Key="DangerBrush" Color="#FF1214" />
</ResourceDictionary>

在App.xaml中引入默认主题对应的资源,默认使用两色主题,这里引入Light.xaml。如下所示:

<Application
    x:Class="Test.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!--使用相对位置引入资源字典文件-->
                <ResourceDictionary Source="Colors/LightColor.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

颜色切换

将颜色应用到窗口程序中,设置窗口的背景颜色和卡片的边框颜色。

<Window
    x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:Test"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="400"
    Height="400"
    Background="{DynamicResource PageBackgroundBrush}"
    mc:Ignorable="d">
    <Grid>
        <StackPanel>
            <TextBlock
                FontSize="24"
                Foreground="{DynamicResource DangerBrush}"
                Text="Hello, World!" />
            <Button
                Margin="5"
                Padding="10"
                Background="{DynamicResource PrimaryBrush}"
                Click="Button_Click"
                Content="切换主题"
                Foreground="White" />
            <Border
                Width="100"
                Height="100"
                Margin="10"
                BorderBrush="{DynamicResource BorderBrush}"
                BorderThickness="1" />
        </StackPanel>
    </Grid>
</Window>

在按钮的响应事件中替换对应的资源字典文件,将原来的资源字典文件移除即可。

private void Button_Click(object sender, RoutedEventArgs e)
{
    List<ResourceDictionary> dictionaryList = new List<ResourceDictionary>();
    foreach (ResourceDictionary dictionary in Application.Current.Resources.MergedDictionaries)
    {
        dictionaryList.Add(dictionary);
    }
    ResourceDictionary defaults = dictionaryList.FirstOrDefault(d => d.Source.OriginalString.EndsWith("Color.xaml"));
    Application.Current.Resources.MergedDictionaries.Remove(defaults);
    string requestedColor = $@"pack://application:,,,/Colors/{(isDark ? "Light" : "Dark")}Color.xaml";
    ResourceDictionary resourceDictionary = new ResourceDictionary() { Source = new Uri(requestedColor) };
    Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
    isDark = !isDark;
}

最后运行起来,点击“切换主题”按钮即可看到效果。

发布时间:2025-05-08
其他阅读

Windows的刘海生成器

其实是很早之前在论坛讨论当时苹果率先推出了带刘海的 mac book pro 的时候,就花了几分钟做了一个模拟刘海的软件,可以给 Windows 系统加上刘海。

查看原文

使用中间件记录网站访问日志记录

对于网站访问日志的记录,一般情况下都是使用现有的日志服务,比如谷歌分析引入轻量 js 文件即可。本文主要介绍对于现有的 Asp.Net Core 网站使用中间件快速记录访问日志。使用中间件的好处:在服务端进行处理,无视客户端类型(特殊信息无法获取);统一处理,不需要对每个地址重复处理等。

查看原文

什么是上帝对象

上帝对象(God Object)是面向对象编程(OOP)中一种特殊现象,在面向对象编程中,我们把逻辑和数据封装成一个个对象,每个对象各司其职,最终实现我们的业务,但是如果业务复杂的情况下,可能会出现一个对象封装太多的数据或者担任了太多的职责的情况,这样的对象我们称为上帝对象。

查看原文

C#桌面应用置顶

Winform和WPF开发中,有时会有需要置顶窗体的需求,本文就介绍怎么使用Win32API进行置顶

查看原文

Angular中制作一个按钮组件

本文将会介绍如何在Angular中制作一个按钮组件,直接在原生按钮上添加特性即可使用,还提供多种颜色方便切换。

查看原文