diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 729bbaa4b3..a893c74324 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -567,10 +567,8 @@ namespace Avalonia.Controls /// public override void Hide() { - try + using (FreezeVisibilityChangeHandling()) { - IgnoreVisibilityChange = true; - if (!_shown) { return; @@ -596,10 +594,6 @@ namespace Avalonia.Controls IsVisible = false; _shown = false; } - finally - { - IgnoreVisibilityChange = false; - } } /// @@ -615,7 +609,7 @@ namespace Avalonia.Controls protected override void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e) { - if (!IgnoreVisibilityChange) + if (!IgnoreVisibilityChanges) { var isVisible = e.GetNewValue(); @@ -685,12 +679,10 @@ namespace Avalonia.Controls private void ShowCore(Window? owner) { - try + using (FreezeVisibilityChangeHandling()) { - IgnoreVisibilityChange = true; - EnsureStateBeforeShow(); - + if (owner != null) { EnsureParentStateBeforeShow(owner); @@ -733,10 +725,6 @@ namespace Avalonia.Controls Renderer?.Start(); OnOpened(EventArgs.Empty); } - finally - { - IgnoreVisibilityChange = false; - } } /// @@ -766,19 +754,17 @@ namespace Avalonia.Controls /// public Task ShowDialog(Window owner) { - try + using (FreezeVisibilityChangeHandling()) { - IgnoreVisibilityChange = true; - EnsureStateBeforeShow(); - + if (owner == null) { throw new ArgumentNullException(nameof(owner)); } - + EnsureParentStateBeforeShow(owner); - + if (_shown) { throw new InvalidOperationException("The window is already being shown."); @@ -828,10 +814,6 @@ namespace Avalonia.Controls OnOpened(EventArgs.Empty); return result.Task; } - finally - { - IgnoreVisibilityChange = false; - } } private void UpdateEnabled() diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index 46653c8203..b71dc6df44 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -42,9 +42,11 @@ namespace Avalonia.Controls private bool _hasExecutedInitialLayoutPass; private bool _isActive; - protected bool IgnoreVisibilityChange { get; set; } + private int _ignoreVisibilityChanges; private WindowBase? _owner; + protected bool IgnoreVisibilityChanges => _ignoreVisibilityChanges > 0; + static WindowBase() { IsVisibleProperty.OverrideDefaultValue(false); @@ -66,6 +68,11 @@ namespace Avalonia.Controls impl.PositionChanged = HandlePositionChanged; } + protected IDisposable FreezeVisibilityChangeHandling() + { + return new IgnoreVisibilityChangesDisposable(this); + } + /// /// Fired when the window is activated. /// @@ -125,18 +132,12 @@ namespace Avalonia.Controls /// public virtual void Hide() { - IgnoreVisibilityChange = true; - - try + using (FreezeVisibilityChangeHandling()) { Renderer?.Stop(); PlatformImpl?.Hide(); IsVisible = false; } - finally - { - IgnoreVisibilityChange = false; - } } /// @@ -144,9 +145,7 @@ namespace Avalonia.Controls /// public virtual void Show() { - IgnoreVisibilityChange = true; - - try + using (FreezeVisibilityChangeHandling()) { EnsureInitialized(); ApplyStyling(); @@ -157,14 +156,11 @@ namespace Avalonia.Controls LayoutManager.ExecuteInitialLayoutPass(); _hasExecutedInitialLayoutPass = true; } + PlatformImpl?.Show(true, false); Renderer?.Start(); OnOpened(EventArgs.Empty); } - finally - { - IgnoreVisibilityChange = false; - } } /// @@ -202,23 +198,17 @@ namespace Avalonia.Controls protected override void HandleClosed() { - IgnoreVisibilityChange = true; - - try + using (FreezeVisibilityChangeHandling()) { IsVisible = false; - + if (this is IFocusScope scope) { FocusManager.Instance?.RemoveFocusScope(scope); } - + base.HandleClosed(); } - finally - { - IgnoreVisibilityChange = false; - } } /// @@ -320,7 +310,7 @@ namespace Avalonia.Controls protected virtual void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e) { - if (!IgnoreVisibilityChange) + if (_ignoreVisibilityChanges == 0) { if ((bool)e.NewValue!) { @@ -332,5 +322,21 @@ namespace Avalonia.Controls } } } + + private readonly struct IgnoreVisibilityChangesDisposable : IDisposable + { + private readonly WindowBase _windowBase; + + public IgnoreVisibilityChangesDisposable(WindowBase windowBase) + { + _windowBase = windowBase; + _windowBase._ignoreVisibilityChanges++; + } + + public void Dispose() + { + _windowBase._ignoreVisibilityChanges--; + } + } } }