|
|
|
@ -103,7 +103,7 @@ namespace Avalonia.Controls |
|
|
|
private static readonly HashSet<Control> _loadedQueue = new HashSet<Control>(); |
|
|
|
private static readonly HashSet<Control> _loadedProcessingQueue = new HashSet<Control>(); |
|
|
|
|
|
|
|
private bool _isLoaded = false; |
|
|
|
private LoadState _loadState = LoadState.Unloaded; |
|
|
|
private DataTemplates? _dataTemplates; |
|
|
|
private Control? _focusAdorner; |
|
|
|
private AutomationPeer? _automationPeer; |
|
|
|
@ -151,7 +151,7 @@ namespace Avalonia.Controls |
|
|
|
/// <remarks>
|
|
|
|
/// This is set to true while raising the <see cref="Loaded"/> event.
|
|
|
|
/// </remarks>
|
|
|
|
public bool IsLoaded => _isLoaded; |
|
|
|
public bool IsLoaded => _loadState == LoadState.Loaded; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets a user-defined object attached to the control.
|
|
|
|
@ -293,9 +293,10 @@ namespace Avalonia.Controls |
|
|
|
/// </summary>
|
|
|
|
internal void ScheduleOnLoadedCore() |
|
|
|
{ |
|
|
|
if (_isLoaded == false) |
|
|
|
if (_loadState == LoadState.Unloaded) |
|
|
|
{ |
|
|
|
bool isAdded = _loadedQueue.Add(this); |
|
|
|
_loadState = LoadState.LoadPending; |
|
|
|
|
|
|
|
if (isAdded && |
|
|
|
_isLoadedProcessing == false) |
|
|
|
@ -312,13 +313,18 @@ namespace Avalonia.Controls |
|
|
|
/// </summary>
|
|
|
|
internal void OnLoadedCore() |
|
|
|
{ |
|
|
|
if (_isLoaded == false && |
|
|
|
if (_loadState == LoadState.LoadPending && |
|
|
|
((ILogical)this).IsAttachedToLogicalTree) |
|
|
|
{ |
|
|
|
_isLoaded = true; |
|
|
|
_loadState = LoadState.Loaded; |
|
|
|
|
|
|
|
OnLoaded(new RoutedEventArgs(LoadedEvent, this)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// We somehow got here while being detached?
|
|
|
|
_loadState = LoadState.Unloaded; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -327,15 +333,21 @@ namespace Avalonia.Controls |
|
|
|
/// </summary>
|
|
|
|
internal void OnUnloadedCore() |
|
|
|
{ |
|
|
|
if (_isLoaded) |
|
|
|
switch (_loadState) |
|
|
|
{ |
|
|
|
// Remove from the loaded event queue here as a failsafe in case the control
|
|
|
|
// is detached before the dispatcher runs the Loaded jobs.
|
|
|
|
_loadedQueue.Remove(this); |
|
|
|
case LoadState.Loaded: |
|
|
|
_loadState = LoadState.Unloaded; |
|
|
|
|
|
|
|
OnUnloaded(new RoutedEventArgs(UnloadedEvent, this)); |
|
|
|
break; |
|
|
|
|
|
|
|
_isLoaded = false; |
|
|
|
case LoadState.LoadPending: |
|
|
|
// Remove from the loaded event queue here as a failsafe in case the control
|
|
|
|
// is detached before the dispatcher runs the Loaded jobs.
|
|
|
|
_loadedQueue.Remove(this); |
|
|
|
|
|
|
|
OnUnloaded(new RoutedEventArgs(UnloadedEvent, this)); |
|
|
|
_loadState = LoadState.Unloaded; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -561,5 +573,12 @@ namespace Avalonia.Controls |
|
|
|
_loadedProcessingQueue.Clear(); |
|
|
|
_isLoadedProcessing = false; |
|
|
|
} |
|
|
|
|
|
|
|
private enum LoadState : byte |
|
|
|
{ |
|
|
|
Unloaded, |
|
|
|
Loaded, |
|
|
|
LoadPending |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|