I'm trying to get a button to change colour once an action is taken. My button's background is set to SystemControlBackgroundAccentBrush
and I basically want to get the 'opposite/complementary' colour once it is clicked.
I found this article:
Using a complimentary accent color
Which seems like what I was looking for. I've had to modify the code a bit as it seems to be specific to windows phone rather than UWP. Below is the class I changed but note that I did not include the entire code from the article above as it was left unchanged:
public class AccentComplimentBrush : ViewModelBase
{
/// <summary>
/// The resource name - as it can be referenced by within the app
/// </summary>
private const string ResourceName = "AccentComplimentBrush";
/// <summary>
/// Initializes a new instance of the <see
cref="AccentComplimentBrush"/> class.
/// </summary>
public AccentComplimentBrush()
{
try
{
//// This doesn't work in the designer - so don't even try
if (this.IsInDesignMode)
{
return;
}
// Make sure we don't try and add the resource more than once - would
//happen if referenced on multiple pages or in app and page(s)
if (!Application.Current.Resources.ContainsKey(ResourceName))
{
var currentAccentColorHex = (SolidColorBrush)Application.Current.Resources["SystemControlBackgroundAccentBrush"];
var hsl = HslColor.FromColor(currentAccentColorHex.Color);
hsl.ConvertToCompliment();
Color compliment = hsl.ToColor();
Application.Current.Resources.Add(ResourceName, new SolidColorBrush(compliment));
}
}
catch (Exception exc)
{
System.Diagnostics.Debug.WriteLine("Something went wrong - ask for your money back");
System.Diagnostics.Debug.WriteLine(exc);
}
}
}
This is how it's called from XAML:
First the class is initialized (and it gets initialized ok)
<UserControl.Resources>
<common:AccentComplimentBrush x:Key="AccentComplimentBrush" />
</UserControl.Resources>
When it goes through the code of the above class, it finds the relevant resource, gets the relevant colour, gets the complementary colour and converts it back to a resource and adds it to the application's resource. As mentioned, I've checked all of that and it all works fine.
Note that it's a circular button and it contains an ellipse which is where I'm trying to assign the stroke and fill properties to the new brush:
<Ellipse Stroke="{StaticResource AccentComplimentBrush}"
Fill="{StaticResource AccentComplimentBrush}"
StrokeThickness="2">
</Ellipse>
This is the error I get:
The text associated with this error code could not be found. Failed to assign to property 'Windows.UI.Xaml.Shapes.Shape.Fill'. [Line: 301 Position: 46]
From the error it looks like it has a problem assigning the 'brush' that's generated by the class.
Note that the Ellipse
code works just fine if I hardcode a ThemeResource
or an actual colour.
Any ideas how I can resolve this? Is there a simpler solution?
Thanks.
Solution is simply modifying the Key
to anything other than AccentComplimentBrush
.
<common:AccentComplimentBrush x:Key="whatever" />
Yes, inside the constructor of the AccentComplimentBrush
class, the complimentary color (a SolidColorBrush) is first added to the resource dictionary with the key AccentComplimentBrush
.
But after the constructor has finished, an instance of AccentComplimentBrush class
(which is a subclass of ViewModelBase) is added to the resource dictionary with the same key, and replace your complimentary color.
So eventually XAML will assign a ViewModelBase to the Fill property at runtime, thus the error.