Multiple color schemes depending on build configuration in WPF-application

32 Views Asked by At

I have a .NET8.0 WPF project where I have multiple release build configurations. I want to have different color schemes depending on the config when I building the project.

My resource dictionary StyleDictionary.xaml is looking like this

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

<!-- Colors and brushes -->
<Color x:Key="PrimaryBlue1">#009CDD</Color>
<Color x:Key="PrimaryBlue2">#68BDEF</Color>
<Color x:Key="PrimaryBlue3">#9BD3F4</Color>
<Color x:Key="PrimaryBlue4">#CDE9FA</Color>

<SolidColorBrush x:Key="MyProgramAccent"
                 Color="{StaticResource PrimaryBlue1}" />
<SolidColorBrush x:Key="MyProgramAccentLighter"
                 Color="{StaticResource PrimaryBlue2}" />

and is included in app.xaml like this

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="./Resources/StyleDictionary.xaml" />
    </ResourceDictionary>
</Application.Resources>

I want to have a second stylesheet setting my brushes "MyProgramAccet" and "MyProgramAccet" with the color that build. In the .csproj file you can have a "Condition" attribute to many of the items or resources like

Condition="'$(Configuration)'=='Release1'

but I can't find that here.

I thought of having a OnStartup override in app.xaml.cs where I change the file depending on the config but this can not build due to not finding the keys of the solid brushes when compiling

        protected override void OnStartup(StartupEventArgs e)
    {
        Resources.MergedDictionaries.Clear();
        var assemblyConfigurationAttribute = typeof(App).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>();
        var buildConfigurationName = assemblyConfigurationAttribute?.Configuration;

        if (buildConfigurationName == "Release1")
        {
            Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("pack://application:,,,/Resources/StyleDictionary2.xaml")
            });
        }
        else
        {
            Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri("pack://application:,,,/Resources/StyleDictionary2.xaml")
            });

        }
        MainWindow mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
        mainWindow.Show();
        base.OnStartup(e);
    }

How should I think here?

1

There are 1 best solutions below

0
BionicCode On

You must reference all dynamic resources using the DynamicResource markup extension.

For example:

<Button Background="{DynamicResource MyProgramAccent}" />

This way the XAML parser will not try to evaluate the referenced resource at compiletime. Instead, the reference will be resolved at runtime.

Changing a ResourceDictionary at runtime triggers a layout invalidation of the owner which results in all dynamic resources being reapplied: if the references are specified using DynamicResource then the referencing property will reevaluate the reference that now potentially points to a new different resource- like in your case.