0

I am playing with this awesome helper Windows Phone Theme Manager in order to allow users to specify a different accent color from the phone's built-in one.

However, what I've found is that the method

ThemeManager.SetAccentColor(AccentColor.Red); 

doesn't work when I use Color resources instead of Brush ones in the xaml. For example, the first Grid below still uses the phone's accent color; while the second one uses whatever I defined in the SetAccentColor method.

<Grid x:Name="NotWorking"> <Grid.Background> <SolidColorBrush Color="{StaticResource PhoneAccentColor}"/> </Grid.Background> </Grid> <Grid x:Name="WorkingFine" Background="{StaticResource PhoneAccentBrush}"/> 

The problem seems to be in this particular method below (in this case the prefix is "PhoneAccent"). Because the Color resource is a value type, changing the currentColor doesn't have any impact to the actual resource.

internal static void SetOrCreateColorAndBrush(string prefix, Color color) { var currentColor = new Color(); // Check if the Colour is actually in the dictionary if (Application.Current.Resources.Contains(prefix + "Color")) { currentColor = (Color)Application.Current.Resources[prefix + "Color"]; currentColor.A = color.A; currentColor.B = color.B; currentColor.G = color.G; currentColor.R = color.R; } 

And then I tried setting the resource to color directly like this -

Application.Current.Resources[prefix + "Color"] = color; 

Only later I discovered this also wouldn't work because of this.

My last try was to remove this resource from Application.Current.Resources and add it back again with the color value. However for some reason that I don't know, this resource still could be found in the resources even after the Remove method...

Application.Current.Resources.Remove(prefix + "Color"); var stilReturnsTrue = Application.Current.Resources.Contains(prefix + "Color"); 

I am kinda running out of ideas here. Wonder if anyone has come across this and found any workarounds?

2
  • Your issue regarding Color vs Brush in the XAML is because you are using StaticResource to bind to the Color and Brush. StaticResource can listen to changes of properties within the object (Brush's Color prop), but not the object itself. Commented Nov 24, 2013 at 8:23
  • @emedbo, I don't think the issue is about StaticResource at all. The problem is how to set the value, not how to update the value on the UI. Note that the Brush one works fine. Commented Nov 24, 2013 at 8:50

2 Answers 2

1

First option is to use everywhere only the PhoneAccentBrush, if it's possible.

The other option I'd suggest is to use your own property of type Color in your ViewModel, that will be used on all appropriate places using DataBinding.
At the start you set this property with current accent color from Application.Current.Resources and later you can change this value on demand and it will be propagated as expected to all places where it's used.
The only problem here is that you cannot use this color in animations, because animations require either fixed values or static resources.

// in "MVVM Light (PCL)" class ObservableObject public Color MyPhoneAccentColor { get { return myPhoneAccentColor; } set { Set(ref myPhoneAccentColor, value); } } private Color myPhoneAccentColor; // in XAML <Grid x:Name="NotWorking"> <Grid.Background> <SolidColorBrush Color="{Binding MyPhoneAccentColor}"/> </Grid.Background> </Grid> 
Sign up to request clarification or add additional context in comments.

3 Comments

+1, however I can't accept this as an answer 'cause I need it particularly for animations...
I don't think you can change colors in your animations defined in XAML at all - they use fixed values. Unless you create all animations programatically when you need them.
I am using them as StaticResource in ColorAnimation. e.g. <ColorAnimation To={StaticResource PhoneAccentColor} ... /> You know what, because the To and From property are indeed a dependency properties, I can actually animate them using the bindings! If you modify your answer a little bit I will happily accept it as the answer. :)
1

I've written and debuged a code below:

 private void myButton_Click(object sender, RoutedEventArgs e) { Color myColor = (Color)App.Current.Resources["PhoneAccentColor"]; App.Current.Resources.Remove("PhoneAccentColor"); bool contains = App.Current.Resources.Contains("PhoneAccentColor"); App.Current.Resources.Add("PhoneAccentColor", Colors.Brown); Color myCol = (Color)App.Current.Resources["PhoneAccentColor"]; // Below works LayoutRoot.Background = new SolidColorBrush((Color)App.Current.Resources["PhoneAccentColor"]); // Not working as you have to change Brush separately LayoutRoot.Background = (Brush)App.Current.Resources["PhoneAccentBrush"]; // Now working App.Current.Resources.Add("PhoneAccentBrush", new SolidColorBrush(Colors.Cyan)); LayoutRoot.Background = (Brush)App.Current.Resources["PhoneAccentBrush"]; return; } 

EDIT
It's working properly - but it's not the Resource you were looking for - it's just creating 'local' Resource which doesn't affect the 'real' PhoneAccentBrush - if you create new Page with Background from StaticResource it will have the default PhoneAccentBrush.
But what I managed to do:

 private void myButton_Click(object sender, RoutedEventArgs e) { Color myColor = (Color)App.Current.Resources["PhoneAccentColor"]; myColor.A = 255; myColor.B = 75; myColor.G = 150; myColor.R = 150; SolidColorBrush internalBrush = (SolidColorBrush)App.Current.Resources["PhoneAccentBrush"]; internalBrush.Color = myColor; return; } 

You cannot remove or override PhoneAccentBrush, but 'locally' (for your App) you can change it's properties. It works quite fine - after this Clisk event, when I create new Page, the PhoneAccentBrush is just as I've set it.

3 Comments

+1, interesting! I just tested, the Add did override the original but if you have the Color resource defined in the xaml, it still shows the default accent color for some reason. However, if I try a custom color, then it works fine...
@Xin I've edited my post after some thinking. There is a way how you can affect color in xaml.
Yes, a Brush would work fine, like what I stated in my post, but if you try to change the Color in the xaml, you simply can't. I think the only way is to create your own Color in the resource...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.