WPF: Changing Resources (colors) from the App.xaml during runtime

Andreas Grech picture Andreas Grech · Apr 24, 2009 · Viewed 29.4k times · Source

I am trying to make my application more customizable by allowing users to pick a color from a Color Picker dialog, and then changing the style of the application in real time (with DynamicResource)

How do I go about in changing specific resources that reside in the app.xaml ?


I have tried something like this but no luck (just a test):

var colorDialog = new CustomControls.ColorPickerDialog();
var dResult = colorDialog.ShowDialog();
var x = Application.Current.Resources.Values.OfType<LinearGradientBrush>().First();
x = new LinearGradientBrush();
x.GradientStops.Add(new GradientStop(colorDialog.SelectedColor,1));

This an excerpt of the app.xaml file:

<Application.Resources>
    <LinearGradientBrush x:Key="HeaderBackground" StartPoint="0.5,0" EndPoint="0.5,1">
        <GradientStop Color="#82cb02" Offset="1"/>
        <GradientStop Color="#82cb01" Offset="0.2"/>
        <GradientStop Color="#629a01" Offset="0.5"/>
    </LinearGradientBrush>
</Application.Resources>

What is the best way to allow this form of customizability (basically just changing some colors) to an application?


[Update]

I just found this answer from a previous question that was asked, and tried it but I am getting the same InvalidOperationException exception Petoj mentioned in the comments for the given answer. Here is the sample code from the answer:

Xaml:

<LinearGradientBrush x:Key="MainBrush" StartPoint="0,0.5" EndPoint="1,0.5" >
    <GradientBrush.GradientStops>
        <GradientStop Color="Blue" Offset="0" />
        <GradientStop Color="Black" Offset="1" />
    </GradientBrush.GradientStops>
</LinearGradientBrush>

C#:

LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush;
myBrush.GradientStops[0].Color = Colors.Red;

Answer

Will Eddins picture Will Eddins · Apr 24, 2009

It looks like you're trying to do some sort of skinning?

I'd recommend defining the resources in a Resource Dictionary contained in a separate file. Then in code (App.cs to load a default, then elsewhere to change) you can load the resources as so:

//using System.Windows
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative);

Application.Current.Resources.MergedDictionaries.Add(dict);

You could also define the default resource dictionary in App.xaml and unload it in code just fine.

Use the MergedDictionaries object to change the dictionary you're using at runtime. Works like a charm for changing an entire interface quickly.