This guide explains when and how to use CustomThemeApplicator to integrate Flowery.Uno's theme controls into apps with existing theming architectures. For general theme management, see DaisyThemeManager.
The default DaisyThemeManager.ApplyTheme() works by adding/removing palette resources from Application.Resources.MergedDictionaries. This works great for simple apps, but you may need CustomThemeApplicator if:
| Scenario | Why Default Doesn't Work |
|---|---|
Custom MergedDictionaries in Application.Resources |
Resource resolution conflicts; bindings don't refresh |
| Theme persistence needed | Default doesn't save to settings |
| Additional actions on theme change | Logging, analytics, UI updates, etc. |
| Complex resource hierarchies | Multiple ResourceDictionaries that need coordinated updates |
If your app works fine with the default behavior, you don't need CustomThemeApplicator.
You have an Uno/WinUI app with custom resources in Application.Resources:
<!-- App.xaml (before Flowery.Uno) -->
<Application ...>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///Themes/CustomResources.xaml" />
<ResourceDictionary Source="ms-appx:///Themes/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="MyCustomBrush" Color="#808080"/>
</ResourceDictionary>
</Application.Resources>
</Application>
Add the Flowery.Uno library reference and include the theme resources:
> Namespace Note: Flowery.Uno uses the namespace Flowery.Controls for all controls.
<!-- App.xaml (with Flowery.Uno added) -->
<Application ...
xmlns:controls="using:Flowery.Controls">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Your existing resources -->
<ResourceDictionary Source="ms-appx:///Themes/CustomResources.xaml" />
<ResourceDictionary Source="ms-appx:///Themes/Icons.xaml" />
<!-- Add Flowery.Uno resources -->
<ResourceDictionary Source="ms-appx:///Flowery.Uno/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Initialize the theme in your App.xaml.cs:
// App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
// Initialize default tokens and apply a theme
DaisyTokenDefaults.EnsureDefaults();
DaisyThemeManager.ApplyTheme("Dark");
// ... rest of your startup code
}
Your views now use Daisy resources:
<Border Background="{ThemeResource DaisyBase200Brush}"
BorderBrush="{ThemeResource DaisyBase300Brush}">
<TextBlock Foreground="{ThemeResource DaisyBaseContentBrush}"
Text="Hello Flowery!"/>
</Border>
You add DaisyThemeDropdown for runtime theme switching:
<controls:DaisyThemeDropdown Width="220"/>
What happens:
The colors don't update. If you restart the app, it's still using the old theme.
DaisyThemeDropdown internally calls DaisyThemeManager.ApplyTheme(), which modifies Application.Resources.MergedDictionaries.
If your app has complex resource hierarchies, the new palette may not refresh properly because:
1. WinUI/Uno resource resolution may not trigger a full refresh for MergedDictionaries changes
2. Controls may still see cached brush values from ThemeResource bindings
3. The theme change doesn't automatically persist across app restarts
Note: This issue depends on your specific resource setup. Many apps work fine with the default; others need custom handling.Write a method that applies themes the way your app needs:
// App.xaml.cs
public static bool ApplyThemeCustom(string themeName)
{
var themeInfo = DaisyThemeManager.GetThemeInfo(themeName);
if (themeInfo == null) return false;
var app = Application.Current;
if (app?.Resources == null) return false;
// Get the palette from DaisyPaletteFactory
var palette = DaisyPaletteFactory.CreatePalette(themeInfo.Name);
if (palette == null) return false;
// Remove existing Daisy palette if present
var existingPalette = app.Resources.MergedDictionaries
.FirstOrDefault(d => d.ContainsKey("DaisyBase100Brush"));
if (existingPalette != null)
{
app.Resources.MergedDictionaries.Remove(existingPalette);
}
// Add new palette
app.Resources.MergedDictionaries.Add(palette);
// Optional: Persist to settings
// Windows.Storage.ApplicationData.Current.LocalSettings.Values["Theme"] = themeName;
// Notify any listeners
DaisyThemeManager.RaiseThemeChanged(themeName);
return true;
}
// App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
// Tell Flowery.Uno to use your custom applicator
DaisyThemeManager.CustomThemeApplicator = ApplyThemeCustom;
// Initialize tokens
DaisyTokenDefaults.EnsureDefaults();
// Load saved theme or use default
var savedTheme = Windows.Storage.ApplicationData.Current.LocalSettings.Values["Theme"] as string;
DaisyThemeManager.ApplyTheme(savedTheme ?? "Dark");
// ... rest of your startup code
}
DaisyThemeDropdown works ✓DaisyThemeController works ✓ DaisyThemeRadio works ✓If the default theme application works but you want to save the selected theme:
DaisyThemeManager.CustomThemeApplicator = themeName =>
{
// Apply theme using default logic
var result = DaisyThemeManager.ApplyThemeInternal(themeName);
if (result)
{
// Persist the theme
Windows.Storage.ApplicationData.Current.LocalSettings.Values["Theme"] = themeName;
}
return result;
};
DaisyThemeManager.CustomThemeApplicator = themeName =>
{
// Use your logging framework
Debug.WriteLine($"Theme changing to: {themeName}");
// Optional: track with your analytics service
// Analytics.Track("theme_changed", new { theme = themeName });
// Do the actual theme application
return ApplyThemeCustom(themeName);
};
DaisyThemeManager.CustomThemeApplicator = themeName =>
{
var result = ApplyThemeCustom(themeName);
if (result)
{
// Update other UI elements
MainViewModel.Instance?.RefreshColors();
// Notify plugins or other components
EventAggregator.Publish(new ThemeChangedEvent(themeName));
}
return result;
};
| Before CustomThemeApplicator | After |
|---|---|
| Built-in theme controls may not work with custom resource setups | All controls work seamlessly |
| Had to build custom theme UI | Use DaisyThemeDropdown etc. directly |
| Theme persistence required separate handling | Persistence built into your applicator |
| Complex workarounds | Single line of setup |
The CustomThemeApplicator pattern gives you full control over how themes are applied while still benefiting from Flowery.Uno's theme UI controls.
Windows.Storage.ApplicationData.Current.LocalSettings for theme persistenceThemeResource bindings work but may need explicit refresh for dynamic changesWhen Flowery.Uno adds support for additional platforms:
Preferences from MAUI Essentials if available