Applying Fluent Design in WPF Without Extra Libraries

This article explains how to apply Fluent styling in WPF using only built-in features, with App.xaml theme setup and SystemColors-based color tracking.

Overview

This article describes how to bring Fluent-style visual design to a WPF application without adding external UI libraries.
The approach uses built-in WPF styling, spacing, corner radius, visual hierarchy, and SystemColors so the UI can stay aligned with Windows color settings.


Prerequisites / Environment

The measurements in this article were taken in the environment above. systemcolors-values.svg reads the color each SystemColors key returns and its relative luminance; systemcolors-tracking.svg reads the referenced values before and after an application resource is swapped.
The following points were confirmed in that environment:


Problem

The default WPF theme is stable and predictable, but its visual density and spacing often diverge from current Windows design language.
In multi-window business applications, default control styles can make interaction priority less clear, especially when all elements have similar weight and low hierarchy contrast.

A WPF window using the default theme. A heading, body text and a square-cornered button sit on the same surface as the window background.
The same controls under the default theme (Aero2). The card surface is not separated from the background and the button corners are square, which makes it hard to tell which element is the primary action.

Cause / Background

WPF provides flexible rendering and templating, but Fluent-specific visuals are not automatically applied by default.
A Fluent-like result requires explicit decisions for:

SystemColors is important in this context because it allows referencing colors derived from Windows configuration instead of hard-coded values.


What SystemColors actually returns can be read back and checked.

A table of the color each SystemColors key returns along with its relative luminance. WindowColor is white, WindowTextColor is black, HighlightColor is a blue, and AccentColor is a red, all matching the OS settings.
Measured on .NET 10 / Windows 11 in light theme by reading each SystemColors key. relative luminance is the WCAG relative luminance, included to gauge foreground-to-background contrast.

WindowColor and WindowTextColor come out at 1.00 and 0.00, the light-theme values on this machine.
Switching the OS to dark theme swaps them.

HighlightColor is the highlight color of a selected item. The accent color the user picks in personalization settings is a separate key, AccentColor, and the two are easily confused.
The machine used here has its accent set to a red, so the table shows HighlightColor as #FF0078D7 and AccentColor as #FFE2241A. A hard-coded accent will disagree with that setting.

Reading these keys is not by itself enough to follow a later replacement, though.
Reading a color directly, as in SystemColors.WindowColor, bakes in the value as of that read.

A table of the value before and after the system brush is replaced, per way of referencing the color. A brush built from SystemColors.WindowColor stays white; only the side referencing SystemColors.WindowBrushKey through DynamicResource takes the new color.
SystemColors.WindowBrushKey in the application's resources replaced, with both values read on either side of the replacement. What this measures is whether each side follows that replacement; an OS theme switch itself is not measured here.

The directly read side keeps its value; only the side referencing the resource key through DynamicResource takes the new color.
Following a replacement requires referencing a resource key such as SystemColors.WindowBrushKey through DynamicResource, not the color.


Solution

Without external libraries, combine the following:

For .NET 9 Fluent theme adoption across an entire app, App.xaml configuration is the key step.
If setup is done only per window, consistency becomes difficult as new screens are added.


Implementation

1. Enable Fluent Theme in App.xaml

To apply Fluent styling at the application level, configure App.xaml.
In .NET 9, there are two valid options.

Use ThemeMode:

<Application x:Class="Sample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             ThemeMode="System">
  <Application.Resources>
    <ResourceDictionary />
  </Application.Resources>
</Application>

Use the Fluent resource dictionary:

<Application x:Class="Sample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml" />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

Either option is sufficient.
Defining one of them in App.xaml first keeps window-level styling focused on local adjustments and reduces theme drift across screens.

2. Use SystemColors in Window-Level Styling

After app-level theme setup, define local styles for layout hierarchy and interaction feedback.
The following sample uses SystemColors through DynamicResource.

<Window x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Fluent Without External Libraries"
        Width="800" Height="480"
        Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">

  <Window.Resources>
    <Style x:Key="CardBorderStyle" TargetType="Border">
      <Setter Property="Padding" Value="24" />
      <Setter Property="CornerRadius" Value="12" />
      <Setter Property="BorderThickness" Value="1" />
      <Setter Property="Background"
              Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
      <Setter Property="BorderBrush"
              Value="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
    </Style>

    <Style x:Key="FluentLikeButtonStyle" TargetType="Button">
      <Setter Property="Padding" Value="14,8" />
      <Setter Property="Margin" Value="0,12,0,0" />
      <Setter Property="Foreground"
              Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
      <Setter Property="Background"
              Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
      <Setter Property="BorderBrush"
              Value="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
      <Setter Property="BorderThickness" Value="1" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Border x:Name="Root"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="8">
              <ContentPresenter HorizontalAlignment="Center"
                                VerticalAlignment="Center" />
            </Border>
            <ControlTemplate.Triggers>
              <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="Root" Property="Opacity" Value="0.92" />
              </Trigger>
              <Trigger Property="IsPressed" Value="True">
                <Setter TargetName="Root" Property="Opacity" Value="0.82" />
              </Trigger>
              <Trigger Property="IsEnabled" Value="False">
                <Setter TargetName="Root" Property="Opacity" Value="0.55" />
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>

  <Grid Margin="32">
    <Border Style="{StaticResource CardBorderStyle}">
      <StackPanel>
        <TextBlock FontSize="24"
                   FontWeight="SemiBold"
                   Foreground="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
                   Text="WPF Fluent Style" />

        <TextBlock Margin="0,10,0,0"
                   TextWrapping="Wrap"
                   Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"
                   Text="SystemColors enables colors that follow Windows color settings." />

        <Button Style="{StaticResource FluentLikeButtonStyle}"
                Content="Run Action" />
      </StackPanel>
    </Border>
  </Grid>
</Window>

This keeps the implementation dependency-free while improving hierarchy and interaction feedback.
Because key brushes are resolved through DynamicResource, changes in Windows color settings can propagate during runtime.
SystemColors.AccentColorBrushKey can be used where accent emphasis is needed.

A WPF window with the Fluent theme and SystemColors applied. A rounded card holds a heading, body text and a rounded button with generous spacing.
The same composition as the XAML above (heading, body text, button) with ThemeMode and SystemColors applied and no external libraries involved. Compared with the figure in the Problem section, the card surface separates from the background and the rounded corners and spacing establish a hierarchy.

Notes


Alternatives / Comparison

Method Advantages Disadvantages Best suited for
WPF built-in styles + SystemColors No additional package dependencies, easier long-term maintenance, OS color alignment Limited advanced Fluent material effects Existing WPF systems with maintenance-first priorities
External Fluent UI library Faster visual unification with ready-made themes Dependency lifecycle and compatibility checks are required New apps with high UI delivery speed requirements
Fully custom rendering Maximum visual freedom Highest implementation and testing cost Products with strict custom branding requirements

Summary

Fluent-style UI in WPF can be implemented without extra libraries.
The practical baseline is: configure Fluent activation in App.xaml (either ThemeMode or Fluent dictionary), then build visual hierarchy with spacing and corner radius, and reference SystemColors through DynamicResource for Windows-aware color behavior.
This approach is generally the most maintainable option for long-lived WPF applications.