2
votes

I am writing a UWP WinRT app in C#. I found the very useful BitmapIcon class and use it for a grid of icons on the main page of my app. The BitmapIcon class has a Foreground brush that can be used to override the color of the original bitmap which is handy for when something controls the icon colors separate from the picture itself (like a server dictating that an icon be red to show that it's important).

I am using a storyboard animation to change the icon colors (for a flashing effect that I know is not liked these days but I am forced to do it). Here's the code:

        ColorAnimationUsingKeyFrames colorAnimation = new ColorAnimationUsingKeyFrames();
        colorAnimation.Duration = TimeSpan.FromSeconds( 3 );
        colorAnimation.EnableDependentAnimation = true;

        IconImage.Foreground = new SolidColorBrush( iconColor ?? AppSettings.appColor );

        DiscreteColorKeyFrame key1 = new DiscreteColorKeyFrame();
        key1.Value = finishColor;
        key1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds( 0 ) );
        colorAnimation.KeyFrames.Add( key1 );

        LinearColorKeyFrame key2 = new LinearColorKeyFrame();
        key2.Value = startColor;
        key2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds( 3.0 ) );
        colorAnimation.KeyFrames.Add( key2 );

        colorAnimation.RepeatBehavior = RepeatBehavior.Forever;

        Storyboard.SetTargetProperty( colorAnimation, "(BitmapIcon.Foreground).Color" );
        Storyboard.SetTarget( colorAnimation, IconImage );

        // Create a storyboard to apply the animation.
        //Storyboard myStoryboard = new Storyboard();
        animationStoryboard.Children.Add( colorAnimation );
        animationStoryboard.Duration = colorAnimation.Duration;
        animationStoryboard.RepeatBehavior = colorAnimation.RepeatBehavior;
        animationStoryboard.Begin();

This seems to somewhat work. I get no exceptions and the colors do change. The problem is that the changes do not show up in the window. If I resize the app window, the colors can be seen to change as I drag the edge of the window. When I stop, they stop showing a change but the change appears to stil lbe happening in the background invisibly. I can tell that the numbers are changing in the background because of the jump in colors that happen when I stop changing the size of the window for a moment.

It's been a while since I worked on C# UWP WinRT code and I think I'm missing some sort of attribute or property of the Imageicon object, it's Foreground SolidColorBrush, or the Color associated with the SolidColorBrush.

Elsewhere in my code, I use similar methods to animate an opening and closing sidebar on the window. That works and the animation is smooth, as expected.

I need to figure out why the color change seems to happen but without the UI getting updated constantly.

2
I ended up creating two images, one of each color, and then animating the opacity of the top one from 0 to 1. It does not solve the problem but it's a work-around. - David Rector
we are investigating the original issue with the Color property. currently we have workaround in the following case update and it similar as your comment. If we get any updates we will update below. - Nico Zhu - MSFT
Even if it worked, I wouldn't recommend it, because it causes the BitmapIcon to recolorize 60 times a second, which is expensive. (Have to update the color of every pixel.). - Raymond Chen
Sometimes those in charge (the boss) can't be convinced to give up a feature even if it is archaic, annoying, and bad for battery life. - David Rector

2 Answers

1
votes

How can I get the UI to update when animating a color change

I could reproduce this issue, and I have discussed with team, it is a bug, I reported it to related team just now. And you could also post this with Windows feed back hub app.

If I receive any info about this, I will update below. thx!

Update

This isn’t ideal, as it involves 2 animations and 2 separate BitmapIcons, we may be able to tweak it to our liking by only using 1 Animation and having a static image behind the BitmapIcon. Please check the following code.

<Grid>
    <BitmapIcon
        x:Name="IconImageOne"
        Foreground="Red"
        UriSource="ms-appx:///Assets/StoreLogo.png">
        <BitmapIcon.Resources>
            <Storyboard x:Name="animationStoryboard">
                <DoubleAnimation
                    AutoReverse="True"
                    RepeatBehavior="Forever"
                    Storyboard.TargetName="IconImageOne"
                    Storyboard.TargetProperty="Opacity"
                    From="1.0"
                    To="0.0"
                    Duration="0:0:3" />
                <DoubleAnimation
                    AutoReverse="True"
                    RepeatBehavior="Forever"
                    Storyboard.TargetName="IconImageTwo"
                    Storyboard.TargetProperty="Opacity"
                    From="0.0"
                    To="1.0"
                    Duration="0:0:3" />
            </Storyboard>
        </BitmapIcon.Resources>
    </BitmapIcon>

    <BitmapIcon
        x:Name="IconImageTwo"
        Foreground="Green"
        Tapped="IconImage_Tapped"
        UriSource="ms-appx:///Assets/StoreLogo.png" />
</Grid>

Code behind

private void StatAnimation()
{

    animationStoryboard.Begin();
}

private void IconImage_Tapped(object sender, TappedRoutedEventArgs e)
{
    StatAnimation();
}
1
votes

I'm posting this untested answer because I think it is a viable option and might work as well as the workaround that I used (and mentioned as a comment on my original post)...

Set up the code to animate the color in case that ever works in the future. Then also add an animation to alter the opacity of the BitmapIcon between 1.0 and 0.99999, or some other similar values. The Opacity change should cause a refresh of the view/screen while not actually changing the opacity enough for the user to see it. The color change will then be visible because of the opacity update.

I have not tested this since I had to move on after using the two-Bitmapicon workaround.