diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 280853967a..aa0ce50bad 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -177,6 +177,7 @@ namespace Avalonia.Controls private readonly Size _maxPlatformClientSize; private WindowStartupLocation _windowStartupLocation; private bool _shown; + private bool _showingAsDialog; /// /// Initializes static members of the class. @@ -509,6 +510,8 @@ namespace Avalonia.Controls Owner = null; PlatformImpl?.Dispose(); + + _showingAsDialog = false; } private bool ShouldCancelClose(CancelEventArgs? args = null) @@ -601,6 +604,33 @@ namespace Avalonia.Controls ShowCore(null); } + protected override void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e) + { + if (!IgnoreVisibilityChange) + { + var isVisible = e.GetNewValue(); + + if (_shown != isVisible) + { + if(!_shown) + { + Show(); + } + else + { + if (_showingAsDialog) + { + Close(false); + } + else + { + Hide(); + } + } + } + } + } + /// /// Shows the window as a child of . /// @@ -620,63 +650,72 @@ namespace Avalonia.Controls private void ShowCore(Window? parent) { - if (PlatformImpl == null) - { - throw new InvalidOperationException("Cannot re-show a closed window."); - } - - if (parent != null) + try { - if (parent.PlatformImpl == null) + IgnoreVisibilityChange = true; + + if (PlatformImpl == null) { - throw new InvalidOperationException("Cannot show a window with a closed parent."); + throw new InvalidOperationException("Cannot re-show a closed window."); } - else if (parent == this) + + if (parent != null) { - throw new InvalidOperationException("A Window cannot be its own parent."); + if (parent.PlatformImpl == null) + { + throw new InvalidOperationException("Cannot show a window with a closed parent."); + } + else if (parent == this) + { + throw new InvalidOperationException("A Window cannot be its own parent."); + } + else if (!parent.IsVisible) + { + throw new InvalidOperationException("Cannot show window with non-visible parent."); + } } - else if (!parent.IsVisible) + + if (_shown) { - throw new InvalidOperationException("Cannot show window with non-visible parent."); + return; } - } - if (_shown) - { - return; - } - - RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); + RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); - EnsureInitialized(); - ApplyStyling(); - _shown = true; - IsVisible = true; + EnsureInitialized(); + ApplyStyling(); + _shown = true; + IsVisible = true; - var initialSize = new Size( - double.IsNaN(Width) ? Math.Max(MinWidth, ClientSize.Width) : Width, - double.IsNaN(Height) ? Math.Max(MinHeight, ClientSize.Height) : Height); + var initialSize = new Size( + double.IsNaN(Width) ? Math.Max(MinWidth, ClientSize.Width) : Width, + double.IsNaN(Height) ? Math.Max(MinHeight, ClientSize.Height) : Height); - if (initialSize != ClientSize) - { - PlatformImpl?.Resize(initialSize, PlatformResizeReason.Layout); - } + if (initialSize != ClientSize) + { + PlatformImpl?.Resize(initialSize, PlatformResizeReason.Layout); + } - LayoutManager.ExecuteInitialLayoutPass(); + LayoutManager.ExecuteInitialLayoutPass(); - if (PlatformImpl != null && parent?.PlatformImpl is not null) - { - PlatformImpl.SetParent(parent.PlatformImpl); - } + if (PlatformImpl != null && parent?.PlatformImpl is not null) + { + PlatformImpl.SetParent(parent.PlatformImpl); + } - Owner = parent; - parent?.AddChild(this, false); + Owner = parent; + parent?.AddChild(this, false); - SetWindowStartupLocation(parent?.PlatformImpl); + SetWindowStartupLocation(parent?.PlatformImpl); - PlatformImpl?.Show(ShowActivated, false); - Renderer?.Start(); - OnOpened(EventArgs.Empty); + PlatformImpl?.Show(ShowActivated, false); + Renderer?.Start(); + OnOpened(EventArgs.Empty); + } + finally + { + IgnoreVisibilityChange = false; + } } /// @@ -706,68 +745,79 @@ namespace Avalonia.Controls /// public Task ShowDialog(Window owner) { - if (owner == null) - { - throw new ArgumentNullException(nameof(owner)); - } - else if (owner.PlatformImpl == null) - { - throw new InvalidOperationException("Cannot show a window with a closed owner."); - } - else if (owner == this) - { - throw new InvalidOperationException("A Window cannot be its own owner."); - } - else if (IsVisible) - { - throw new InvalidOperationException("The window is already being shown."); - } - else if (!owner.IsVisible) + try { - throw new InvalidOperationException("Cannot show window with non-visible parent."); - } + IgnoreVisibilityChange = true; + + if (owner == null) + { + throw new ArgumentNullException(nameof(owner)); + } + else if (owner.PlatformImpl == null) + { + throw new InvalidOperationException("Cannot show a window with a closed owner."); + } + else if (owner == this) + { + throw new InvalidOperationException("A Window cannot be its own owner."); + } + else if (IsVisible) + { + throw new InvalidOperationException("The window is already being shown."); + } + else if (!owner.IsVisible) + { + throw new InvalidOperationException("Cannot show window with non-visible parent."); + } - RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); + RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); - EnsureInitialized(); - ApplyStyling(); - IsVisible = true; + EnsureInitialized(); + ApplyStyling(); + _shown = true; + _showingAsDialog = true; + IsVisible = true; - var initialSize = new Size( - double.IsNaN(Width) ? ClientSize.Width : Width, - double.IsNaN(Height) ? ClientSize.Height : Height); + var initialSize = new Size( + double.IsNaN(Width) ? ClientSize.Width : Width, + double.IsNaN(Height) ? ClientSize.Height : Height); - if (initialSize != ClientSize) - { - PlatformImpl?.Resize(initialSize, PlatformResizeReason.Layout); - } + if (initialSize != ClientSize) + { + PlatformImpl?.Resize(initialSize, PlatformResizeReason.Layout); + } - LayoutManager.ExecuteInitialLayoutPass(); + LayoutManager.ExecuteInitialLayoutPass(); - var result = new TaskCompletionSource(); + var result = new TaskCompletionSource(); - PlatformImpl?.SetParent(owner.PlatformImpl); - Owner = owner; - owner.AddChild(this, true); + PlatformImpl?.SetParent(owner.PlatformImpl); + Owner = owner; + owner.AddChild(this, true); - SetWindowStartupLocation(owner.PlatformImpl); + SetWindowStartupLocation(owner.PlatformImpl); - PlatformImpl?.Show(ShowActivated, true); + PlatformImpl?.Show(ShowActivated, true); - Renderer?.Start(); + Renderer?.Start(); - Observable.FromEventPattern( - x => Closed += x, - x => Closed -= x) - .Take(1) - .Subscribe(_ => - { - owner.Activate(); - result.SetResult((TResult)(_dialogResult ?? default(TResult)!)); - }); + Observable.FromEventPattern( + x => Closed += x, + x => Closed -= x) + .Take(1) + .Subscribe(_ => + { + owner.Activate(); + result.SetResult((TResult)(_dialogResult ?? default(TResult)!)); + }); - OnOpened(EventArgs.Empty); - return result.Task; + 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 8f1b2198ad..46653c8203 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -42,7 +42,7 @@ namespace Avalonia.Controls private bool _hasExecutedInitialLayoutPass; private bool _isActive; - private bool _ignoreVisibilityChange; + protected bool IgnoreVisibilityChange { get; set; } private WindowBase? _owner; static WindowBase() @@ -125,7 +125,7 @@ namespace Avalonia.Controls /// public virtual void Hide() { - _ignoreVisibilityChange = true; + IgnoreVisibilityChange = true; try { @@ -135,7 +135,7 @@ namespace Avalonia.Controls } finally { - _ignoreVisibilityChange = false; + IgnoreVisibilityChange = false; } } @@ -144,7 +144,7 @@ namespace Avalonia.Controls /// public virtual void Show() { - _ignoreVisibilityChange = true; + IgnoreVisibilityChange = true; try { @@ -163,7 +163,7 @@ namespace Avalonia.Controls } finally { - _ignoreVisibilityChange = false; + IgnoreVisibilityChange = false; } } @@ -202,7 +202,7 @@ namespace Avalonia.Controls protected override void HandleClosed() { - _ignoreVisibilityChange = true; + IgnoreVisibilityChange = true; try { @@ -217,7 +217,7 @@ namespace Avalonia.Controls } finally { - _ignoreVisibilityChange = false; + IgnoreVisibilityChange = false; } } @@ -318,9 +318,9 @@ namespace Avalonia.Controls Deactivated?.Invoke(this, EventArgs.Empty); } - private void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e) + protected virtual void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e) { - if (!_ignoreVisibilityChange) + if (!IgnoreVisibilityChange) { if ((bool)e.NewValue!) {