Using Avalonia Theme Colors and Brushes for Custom UI
Learn how to reference Avalonia theme colors and brushes in XAML and code for custom UI elements. Use DynamicResource, TryGetResource, and ColorPaletteResources to match Fluent or Simple themes dynamically across light and dark variants.
How do I use the active theme’s colors/brushes for custom UI elements in Avalonia?
I’m building a desktop GUI with standard controls and need to add custom visuals (separators, rulers, custom drawings, etc.) that should follow the current theme instead of hardcoding colors. I looked through Avalonia docs and source but remain confused where to find or how to reference semantic/theme colors.
What I’ve found so far:
BaseColorPalette.xaml(Avalonia.Themes.Fluent) defines many theme-dependent colors, but the names are not clearly semantic (which ones are foreground/background/separator?).- Material.Avalonia’s “Brush Names” list is close to what I want but is Material-specific, not for Avalonia’s built-in themes.
ProgressBar.xaml(Simple theme) uses placeholders likeThemeForegroundBrushandThemeAccentBrush, but I can’t find where these are defined or documented.ColorPaletteResourcesseems to contain color definitions, but its names/docs are unclear and say “This class can only be used in Palettes.”- The “How to use theme variants” guide shows declaring custom
BackgroundBrush/ForegroundBrushresources rather than demonstrating how to use the background/foreground brushes that come with the active theme. - Fluent theme docs show palettes and examples but not how to consume pre-defined theme brushes/resources in app XAML or code.
- Resource docs show how to define custom keys, not how to use resources supplied by the active theme.
- A GitHub discussion about getting the accent color ends up defining custom colors again instead of showing how to access theme colors programmatically.
Specific questions:
- How can I reference the active theme’s semantic brushes (foreground, background, accent, separator, etc.) in XAML so custom visuals automatically match the current Avalonia theme?
- Where are keys like
ThemeForegroundBrushandThemeAccentBrushdefined, and what are the canonical resource keys for semantic colors in Avalonia’s built-in themes (Fluent, Simple, etc.)? - Is there a runtime API equivalent to WPF’s
SystemColors/SystemBrushesto retrieve theme colors programmatically in Avalonia? - How do
ColorPaletteResources,BaseColorPalette.xamland palette usage relate — when should I use palettes vs. theme-provided brushes? - What are the recommended best practices or patterns for exposing and consuming semantic theme colors for custom visuals in Avalonia?
In Avalonia, reference active theme colors and brushes like foreground, background, or accent using DynamicResource in XAML for automatic theme switching—keys such as ThemeForegroundBrush (Simple theme) or BrushTextControlForeground (Fluent) pull from the current variant. Programmatically, grab them via Application.Current.TryGetResource(key, ActualThemeVariant) to match the OS or app theme without hardcoding. This keeps custom visuals like separators or rulers in sync across light/dark modes in Avalonia themes.
Contents
- Understanding Avalonia Theme Resources
- Referencing Theme Brushes in XAML
- Retrieving Theme Colors in Code
- Canonical Resource Keys for Built-in Themes
- ColorPaletteResources and Palettes Explained
- Best Practices for Custom UI Elements
Sources
- How To Use Theme Variants | Avalonia Docs
- Fluent Theme | Avalonia Docs
- ColorPaletteResources Class | Avalonia API-Reference
- How to get the accent color for the current theme? · AvaloniaUI/Avalonia · Discussion #13968
- ColorPaletteResources.Properties.cs - Avalonia.Themes.Fluent (GitHub)
- BaseResources.xaml - Avalonia.Themes.Fluent (GitHub)
- FluentControlResources.xaml - Avalonia.Themes.Fluent (GitHub)
Conclusion
Stick to DynamicResource for XAML and TryGetResource in code to keep your custom Avalonia UI elements theme-aware—it’s the cleanest path without reinventing palettes. Dive into the Fluent or Simple theme source files on GitHub for exact keys, and always test light/dark switches. You’ll end up with visuals that feel native, no matter the user’s setup.
Understanding Avalonia Theme Resources
Avalonia’s themes, like Fluent or Simple, don’t hand you a neat “semantic colors” list in the docs. Instead, they pack brushes into ThemeDictionaries keyed to variants (light/dark). Why? So controls and custom bits update automatically when the theme flips—say, from Windows light to dark.
The ActualThemeVariant property on your app, window, or control tells you what’s active right now. Resources in these dictionaries only load via DynamicResource; try StaticResource and you’ll hit a runtime error unless the key exists outside theme scopes. Frustrating at first, but it forces theme fidelity.
Take ProgressBar in the Simple theme: it grabs ThemeForegroundBrush and ThemeAccentBrush. Where do those live? Scattered in theme XAML files, but more on that soon.
Referencing Theme Brushes in XAML
Want a separator line that matches the theme’s subtle background divider? Slap DynamicResource on it. Here’s a quick custom ruler that picks the right stroke:
<Line StrokeThickness="1" Stroke="{DynamicResource ThemeBorderMidBrush}">
<!-- Or for Fluent: Stroke="{DynamicResource BrushDividerStroke}" -->
</Line>
This pulls from the active theme’s dictionary. Switch to dark mode? It updates without a rebuild. But you need the right key—ThemeBorderMidBrush works in Simple; Fluent leans granular like BrushDividerStroke or BrushControlBorderLow.
For a full custom visual, wrap in a UserControl or draw in Canvas. Bind to ActualThemeVariant if you want logic:
<Canvas x:Name="Ruler">
<Canvas.Stroke="{DynamicResource ThemeForegroundBrush}"/>
<!-- Ticks with theme accent -->
<Rectangle Fill="{DynamicResource ThemeAccentBrush}" Width="2" Height="10"/>
</Canvas>
Pro tip: Scope overrides with RequestedThemeVariant="Dark" on a parent, but inherit globally for consistency.
Retrieving Theme Colors in Code
No XAML? Or need brushes for Skia drawing? Avalonia’s got your back with a runtime API akin to WPF’s SystemBrushes, but theme-aware.
Hit up Application.Current.TryGetResource(key, Application.Current.ActualThemeVariant, out var brush). Pass the theme variant, and it fishes from the right dictionary. Example for a custom separator in C#:
var themeVariant = Application.Current.ActualThemeVariant ?? ThemeVariant.Light;
if (Application.Current.TryGetResource("ThemeBorderLowBrush", themeVariant, out var strokeBrush))
{
// Use (ISolidColorBrush)strokeBrush for your drawing context
drawingContext.DrawLine(strokeBrush, startPoint, endPoint);
}
Nail the accent? Same deal: "AccentBrushForeground" or check this GitHub discussion for OS color via PlatformSettings.GetColorValues(). It’s not SystemColors, but close—and variant-specific.
Fallbacks matter: if the key flops, default to ThemeBrush or a solid color. Cache the brush? Sure, but rebinding on theme change keeps it fresh.
Canonical Resource Keys for Built-in Themes
No master list in docs, right? Dig into source. Simple theme keeps it high-level: ThemeForegroundBrush, ThemeBackgroundBrush, ThemeAccentBrush, ThemeBorderLowBrush, ThemeBorderMidBrush.
Fluent? Granular city. From BaseResources.xaml and FluentControlResources.xaml:
- Foreground-ish:
BrushTextControlForeground,BrushForeground - Backgrounds:
BrushBackground,BrushCardBackground - Accents:
AccentBrushPrimary,BrushAccent - Separators/Dividers:
BrushDividerStroke,ThemeBorderLowBrush - Errors:
BrushCriticalFill,BrushCriticalForeground
Full palette feeds these via ColorPaletteResources—props like Accent, BaseLow, RegionColor. Inspect the repo; keys aren’t “semantic” like Material.Avalonia’s, but consistent within a theme.
Simple for basics, Fluent for polish. Mix? Tricky—stick to one.
ColorPaletteResources and Palettes Explained
ColorPaletteResources isn’t for direct use; it’s Fluent’s palette engine. Define overrides like:
<FluentTheme>
<FluentTheme.Palettes>
<ColorPaletteResources x:Key="Light" Accent="#Green" BaseLow="#White"/>
</FluentTheme.Palettes>
</FluentTheme>
This tweaks base colors (Accent, AltHigh, ChromeLow—you name it, API docs list them). Theme brushes derive from these statically at startup (except Accent, which binds runtime).
Use palettes to customize the whole theme, not pluck singles. For consuming? Reference derived brushes as above. BaseColorPalette.xaml? Internal to Fluent, generating from palettes.
When? Override for branding; otherwise, use provided brushes.
Best Practices for Custom UI Elements
Build theme-respecting customs like this:
- XAML first:
DynamicResourceeverywhere. Test variant switches. - Code fallback:
TryGetResourcewithActualThemeVariant. Listen toActualThemeVariantChanged. - Custom controls: Expose
DirectPropertyfor brushes, default to theme lookups. - Performance: Avoid per-frame lookups; subscribe to theme events.
- Discovery: Repo dive or theme.xaml.live editor for previews.
- Cross-theme: If Fluent/Simple toggleable, conditional keys or shared semantics like “Foreground”.
Custom ruler example? Line Stroke="{DynamicResource BrushDividerStroke}"—boom, native feel. Users flip themes? Yours adapts. Skip hardcodes; embrace the dictionaries.
Had the same head-scratcher? Source inspection unlocks it. Your app will shine across platforms.