Skip to content

Loaded/Unloaded/IsLoaded APIs break down on quick swapping #1900

Open
@Sergio0694

Description

@Sergio0694

Describe the bug

As the title says, I've found a way to reproduce an annoying issue in the FrameworkElement.Loaded and FrameworkElement.Unloaded events, and the FrameworkElement.IsLoaded property. Basically, the two events will fire in a completely incorrect order or will not fire at all, and consequently the IsLoaded property will report a value that does not reflect the state of a given element.

In short:

  • An element loaded in the tree has Unloaded raised last
  • An element loaded in the tree reports IsLoaded being false (!)

This is especially an issue because devs are relying on those events to track the lifetime of visual items, eg. to subscribe/unsubscribe to external events, and whatnot. At the moment I've had to come up with specific workarounds in my app Legere to bypass this problem, but it's really not an ideal solution, plus this could be not doable at all in other scenarios where this issue is present.

Steps to reproduce the bug

Steps to reproduce the behavior:

  1. Download this repro: LoadedGlitchRepro.zip
  2. Build and start the app with the attached debugger
  3. Click on any of the command bar buttons

Expected behavior

You should see the output window display the Loaded event last for the second button you clicked. Instead you'll see Unloaded being raised last for the control that you can clearly see being loaded.

Additional steps

  1. Click on some of those buttons at random and just observe the output log. See the screenshot below for an example of the output window. You can see the Loaded and Unloaded events are fired in a completely unreliable and incorrect manner.

Screenshots

image

Version Info

  • Windows 10 Pro 18362.592
  • Tried targeting both the SDK 17763 and the SDK 18632

NuGet package version:

  • Microsoft.UI.Xaml 2.1.190606001 (though this shouldn't be relevant here)
Windows 10 version Saw the problem?
Insider Build (xxxxx)
November 2019 Update (18363)
May 2019 Update (18362) Yes
October 2018 Update (17763)
April 2018 Update (17134)
Fall Creators Update (16299)
Creators Update (15063)
Device form factor Saw the problem?
Desktop Yes
Mobile
Xbox
Surface Hub
IoT

Additional context

The reason why I have a setup like this is that in Legere I have a series of post views that I reuse, to avoid the overhead of creating a completely new instance every time a post of a given type is loaded. They're initially all stored inside an invisible and collapsed Grid, and lazily loaded. When one view is needed, I load it with FindName(string), then place it in a host Border the user can interact with. When the user opens a post of another type, I remove that view and place it back in the original host (so that FindName will work again, as it needs the element to be in the visual tree for it to find it), then repeat the procedure to find and swap in the new view to use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-Lifetimefeature proposalNew feature proposalneeds-winui-3Indicates that feature can only be done in WinUI 3.0 or beyond. (needs winui 3)team-ControlsIssue for the Controls teamwct

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions