Search code examples
wpfxamlapplication-settings

Setting WPF Window Background to Resource Dictionary Brush User Setting


I have two brushes declared in my ResourceDictionary and I would like the user to select which background they want to see on the main window.

Resource Dictionary Brushes:
x:Key="LightBlueMainWindow"
x:Key="DarkBlueMainWindow"

Window:
Background="{DynamicResource LightBlueMainWindow}">

I have a project User Setting defined 'MainBackground' which is a string and can contain either key (LightBlueMainWindow or DarkBlueMainWindow).

What is the best way to dynamically set the background based on the user setting in XAML?

EDIT

I need to mention that I need to access this brush from many different user controls and windows throughout the application. I don't want to set a property on every single place I want to set this brush.

Also, the brushes are pre-defined and not just a color like this

<LinearGradientBrush x:Key="LightBlueMainWindow" EndPoint="0.5,1" 
                     MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>            
        <GradientStopCollection>
            <GradientStop Color="#FFE9EFF3" />
            <GradientStop Color="#FF84A1B8" Offset="1"/>
        </GradientStopCollection>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Solution

  • It will require a couple of steps

    You'll need a converter since you can't bind x:Key of a StaticResource or DynamicResource. For the converter to be able to get easy access to the resources they should be added at appliaction level

    <Application ...>
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="BrushesDictionary.xaml"/>
                </ResourceDictionary.MergedDictionaries>
                <local:ApplicationResourceKeyConverter x:Key="ApplicationResourceKeyConverter"/>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    ApplicationResourceKeyConverter

    public class ApplicationResourceKeyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string key = value as string;
            return Application.Current.TryFindResource(key);
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    Then you can bind the MainWindow Background property to the user settings string MainBackground like

    <Window ...
            xmlns:ProjectProperties="clr-namespace:YourProjectName.Properties" 
            Background="{Binding Source={x:Static ProjectProperties:Settings.Default},
                                 Path=MainBackground,
                                 Converter={StaticResource ApplicationResourceKeyConverter}}">
        <!--...-->
    </Window>