Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/Controls/src/Core/VisualElement/VisualElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2139,17 +2139,26 @@ public bool IsLoaded
}

/// <summary>
/// Occurs when an element has been constructed and added to the object tree.
/// Occurs when an element has been constructed and added to the platform visual tree.
/// </summary>
/// <remarks>This event may occur before the element has been measured so should not be relied on for size information.</remarks>
public event EventHandler? Loaded
{
add
{
bool watchingLoaded = _watchingPlatformLoaded;
_loaded += value;
UpdatePlatformUnloadedLoadedWiring(Window);
if (_isLoadedFired)
_loaded?.Invoke(this, EventArgs.Empty);

// The point of this code, is to fire loaded if the element is already loaded.
//
// If this is the first time the user is subscribing to Loaded,
// UpdatePlatformUnloadedLoadedWiring will take care of firing Loaded.
// If we are already wired up to watch loaded, then we'll fire it off if we know this
// view is in a state where it's been determined that it's accurate to fire
// _isLoadedFired.
if (_isLoadedFired && watchingLoaded)
value?.Invoke(this, EventArgs.Empty);

}
remove
Expand All @@ -2160,7 +2169,7 @@ public event EventHandler? Loaded
}

/// <summary>
/// Occurs when an element is no longer connected to the main object tree.
/// Occurs when an element is no longer connected to the platform visual tree.
/// </summary>
public event EventHandler? Unloaded
{
Expand Down
65 changes: 65 additions & 0 deletions src/Controls/tests/Core.UnitTests/PageLifeCycleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,71 @@ public async Task PushSecondModalPage()
Assert.Equal(1, firstModalPage.AppearingCount);
}

[Fact]
public async Task LoadedUnLoadedEvents()
{
var previousPage = new LCPage();
var lcPage = new LCPage();
var navigationPage =
new TestNavigationPage(true, previousPage)
.AddToTestWindow();

await navigationPage.PushAsync(lcPage);

int loadedCnt = 0;
int unLoadedCnt = 0;
lcPage.Loaded += (_, _) => loadedCnt++;
lcPage.Unloaded += (_, _) => unLoadedCnt++;

Assert.Equal(1, loadedCnt);
Assert.Equal(0, unLoadedCnt);

await navigationPage.PopAsync();

Assert.Equal(1, loadedCnt);
Assert.Equal(1, unLoadedCnt);
}

[Fact]
public async Task LoadedFiresOnInitialSubscription()
{
var previousPage = new LCPage();
var lcPage = new LCPage();
var navigationPage =
new TestNavigationPage(true, previousPage)
.AddToTestWindow();

await navigationPage.PushAsync(lcPage);

int loadedCnt = 0;
int unLoadedCnt = 0;

Assert.True(lcPage.IsLoaded);

// Wire up to loaded event to setup wiring
lcPage.Loaded += (_, _) =>
{
loadedCnt++;
};

// Subscribing to loaded should fire the loaded
// event if the page is already loaded
lcPage.Loaded += (_, _) =>
{
loadedCnt++;
};

lcPage.Unloaded += (_, _) => unLoadedCnt++;

Assert.Equal(2, loadedCnt);
Assert.Equal(0, unLoadedCnt);

await navigationPage.PopAsync();

Assert.Equal(2, loadedCnt);
Assert.Equal(1, unLoadedCnt);
}

public class LCPage : ContentPage
{
public NavigatedFromEventArgs NavigatedFromArgs { get; private set; }
Expand Down