A Failed Experiment - Part Two

A Story About Overengineering, Curiosity, and Debugging Reality

In Part One, I stopped exactly at the moment where curiosity turned into framework archaeology.

Now let’s talk about the real question.

Trying to Use ThemeResources in Code

If you want to use a ThemeResource in code-behind, the first idea that naturally comes to mind is:

fullNameTextBox.Background = App.Current.Resources["SystemFillColorCriticalBackgroundBrush"] as Brush;

Looks correct.

Except… it’s wrong.

This retrieves a static resource.
It will not update when the application theme changes.

So your UI becomes frozen in time while the rest of the app switches between Light and Dark like nothing happened.

Second Idea: Search Inside Theme Dictionaries

The next logical step is to look inside the theme dictionaries. Maybe we can find the resource there and use it directly?

And yes (technically they do) inside the application theme dictionaries.

You might try something like this:

var dict = App.Current.Resources.ThemeDictionaries["Light"] as ResourceDictionary;
var brush = dict["SystemFillColorCriticalBackgroundBrush"] as Brush;

And then…

💥 Exception. Resource not found.

At this point you start questioning reality.

Where Are ThemeResources Actually Stored?

Look at your App.xaml file.

You will find this line:

<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />

This innocent line hides the answer.

XamlControlsResources inherits from ResourceDictionary.

And yes, this is where WinUI stores all default ThemeResources.

So instead of living directly in App.Current.Resources, they come from merged dictionaries injected by WinUI itself.

Diving Deeper - ThemeDictionaries

Inside XamlControlsResources, you’ll find:

ThemeDictionaries
 ├── Default   (Dark theme)
 ├── Light
 └── HighContrast

(Honestly, calling Dark mode “Default” is a design mystery I still haven’t solved.)

And this is the full diagram:

App.Resources
 └── MergedDictionaries
     └── XamlControlsResources
         └── ThemeDictionaries
             ├── Default (Dark)
             ├── Light
             └── HighContrast

Good

We finally found the starting point.

The Next Problem

If you manually access one dictionary:

var brush =
((ResourceDictionary)App.Current.Resources
    .MergedDictionaries[0]
    .ThemeDictionaries["Light"])
["SystemFillColorCriticalBackgroundBrush"];

It works…

but again:
✅ Resource retrieved
❌ Still static

The value will never update automatically when the theme changes.

Which means:

👉 WinUI’s ThemeResource behavior is not just lookup, it is runtime tracking.

So we must implement that behavior ourselves.

The Idea

The solution concept became surprisingly simple:

  1. Apply the resource after the element is loaded.
  2. Reapply it whenever the theme changes.
  3. Listen for system color updates (accent color, High Contrast).
  4. Track elements so the latest assigned resource always wins.

In other words: Recreate ThemeResource behavior… but in C#.

The Helper Class

I created a helper called:

ThemeResourceHelper

Its job is to simulate XAML ThemeResource binding from code.

You can read the full implementation here:

👉 https://github.com/Zakariathr22/NoXamlTheme

How It Works (Conceptually)

1. Attached Binding State

Each FrameworkElement receives an attached state object storing:

2. Automatic Lifecycle Handling

When a resource is applied:

3. Global System Tracking

The helper subscribes once to:

UISettings.ColorValuesChanged

This detects:

4. Choosing the Correct Theme Dictionary

When applying a resource, the helper determines the current theme (Light, Dark, High Contrast) and looks up the resource in the corresponding dictionary.

It then applies the retrieved value to the target property.

What This Means

This approach allows for dynamic theme updates while maintaining a clean and maintainable codebase.

I’ll leave you with the code for now.
You’ll probably notice a problem in it, and that’s exactly where this experiment reached its limit for me.

See you in Part Three.

Bye.


References

⬅ Previous: A Failed Experiment - Part One
decorative gif