C# UWP XAML <Image> ImageOpened event does not fire, and <Storyboard> misbehaving

WoodManEXP 80 Reputation points
2026-04-13T22:42:20.89+00:00

In this XAML segment

        <Image x:Name="Image1" Grid.Row="0" ImageOpened="Image1Opened">
            <Image.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <BeginStoryboard>
                        <Storyboard x:Name="MyStoryboard">
                            <DoubleAnimation Storyboard.TargetName="Image1" 
                                             Storyboard.TargetProperty="Opacity" 
                                             From="0.0" To="1.0" Duration="0:0:2" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Image.Triggers>
        </Image>

Two things are not behaving as expected.

  1. The ImageOpened event is never fired when the code behind sets the Image's Source property. but the image does correctly change to display the new BitmapImage.
  2. On the first code-behind image set in Image.Source the Storyboard performs as expected. But on subsequent code-behind changes to the Image's Source property the StoryBoard seems to jump directly to its To= value. It does not fade in. If the To= value is set to .5 the image immediately appears at half Opacity.

Any thoughts about what might be happening with these two issues?

(This is C# with UWP, Visual Studio Insiders [11626.173])

TY!

Developer technologies | XAML
Developer technologies | XAML

A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.

0 comments No comments

Answer accepted by question author

Nancy Vo (WICLOUD CORPORATION) 6,675 Reputation points Microsoft External Staff Moderator
2026-04-14T03:50:30.53+00:00

Hello @WoodManEXP ,

Thanks for your question.

  1. The ImageOpened event doesn't fire on subsequent image loads because UWP caches image by URI. When you set the same BitmapImage URI again (or even create a new BitmapImage with the same URI), UWP recognizes it's already cached and skips the loading process.

Additionally, subscribing to ImageOpened after calling SetSourceAsync means the event may have already fired before you attached the handler.

I recommend disabling image caching and subscribing to events before loading:

This is code example:

private async Task LoadImageWithFadeAsync(StorageFile imageFile)
{
    MyStoryboard?.Stop();
    Image1.Opacity = 0.0;

    var bitmapImage = new BitmapImage();

    bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;

    bitmapImage.ImageOpened += (s, e) =>
    {
        Debug.WriteLine(" ImageOpened fired!");
        Image1.Opacity = 0.0;
        MyStoryboard?.Begin();
    };

    bitmapImage.ImageFailed += (s, e) =>
    {
        Debug.WriteLine($"Image load failed: {e.ErrorMessage}");
    };

    using (var fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
    {
        await bitmapImage.SetSourceAsync(fileStream);
    }

    Image1.Source = bitmapImage;
}
  1. After the first animation completes, the Opacity property remains at the final value (1.0). When you try to animate again, the animation tries to go from 0.0 to 1.0, but since the current value is already 1.0, it appears to jump immediately to the end state. I recommend resetting the opacity before each animation
private async Task LoadImageWithFadeAsync(StorageFile imageFile)
{
    MyStoryboard?.Stop();
    Image1.Opacity = 0.0;

    var bitmapImage = new BitmapImage();
    bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;

    bitmapImage.ImageOpened += (s, e) =>
    {
        Image1.Opacity = 0.0;
        MyStoryboard?.Begin();
    };

    using (var fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
    {
        await bitmapImage.SetSourceAsync(fileStream);
    }

    Image1.Source = bitmapImage;
}

Note: I noticed your XAML uses <Image.Triggers>. Unfortunately, EventTriggers are not commonly used in UWP. The only trigger that is typically defined is a Loaded trigger (not Image).

Please try and let me know it it works.

I hope this addresses your question. If this response was helpful, please consider following the guidance to provide feedback.

Was this answer helpful?

1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. WoodManEXP 80 Reputation points
    2026-04-13T23:02:44.0866667+00:00

    The suggestions from the AI were unhelpful. For the storyboard part, adding an event handler to the bitmap:

                        await bitmapImage.SetSourceAsync(fileStream);
                        bitmapImage.ImageOpened += (s, e) =>
                        {
                            imageStoryBoard?.Begin();
                        };
                        imagePane?.Source = bitmapImage;
    

    Did not change the behavior Storyboard of the image.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.