xamlwin-universal-appxamlparseexception

Complimentary accent color in XAML - UWP Windows 10


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:

  1. First the class is initialized (and it gets initialized ok)

    <UserControl.Resources>
        <common:AccentComplimentBrush x:Key="AccentComplimentBrush" />
    </UserControl.Resources>
    
  2. 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

  • 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.