From 66c42ac8ec229d891af98f13fe020087a02ebaf4 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 30 Aug 2023 19:11:56 -0700 Subject: [PATCH] Update Host attachment behavior once again --- .../WindowNotificationManager.cs | 68 +++++++------------ .../Primitives/AdornerLayer.cs | 2 +- 2 files changed, 24 insertions(+), 46 deletions(-) diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs index 889e17ba03..cb7ade44b3 100644 --- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs +++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs @@ -1,7 +1,9 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Avalonia.Collections; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Threading; @@ -17,8 +19,6 @@ namespace Avalonia.Controls.Notifications public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager { private IList? _items; - private AdornerLayer? adornerLayer; - /// /// Defines the property. /// @@ -49,34 +49,14 @@ namespace Avalonia.Controls.Notifications get { return GetValue(MaxItemsProperty); } set { SetValue(MaxItemsProperty, value); } } - - /// - /// Defines the property - /// - public static readonly DirectProperty HostProperty = - AvaloniaProperty.RegisterDirect( - nameof(Host), - o => o.Host, - (o, v) => o.Host = v); - - private Visual? _Host; - - /// - /// The Host that this NotificationManger should register to. If the Host is null, the Parent will be used. - /// - public Visual? Host - { - get { return _Host; } - set { SetAndRaise(HostProperty, ref _Host, value); } - } /// /// Initializes a new instance of the class. /// /// The TopLevel that will host the control. - public WindowNotificationManager(TopLevel? host) : this() + public WindowNotificationManager(TopLevel host) : this() { - Host = host; + InstallFromTopLevel(host); } /// @@ -137,6 +117,8 @@ namespace Avalonia.Controls.Notifications Action? onClose = null, string[]? classes = null) { + Dispatcher.UIThread.VerifyAccess(); + var notificationControl = new NotificationCard { Content = content, @@ -194,38 +176,34 @@ namespace Avalonia.Controls.Notifications { UpdatePseudoClasses(change.GetNewValue()); } - - if (change.Property == HostProperty) - { - Install(); - } } /// /// Installs the within the /// - private void Install() + private void InstallFromTopLevel(TopLevel topLevel) { - // unregister from AdornerLayer if this control was already installed - if (adornerLayer is not null && !adornerLayer.Children.Contains(this)) + topLevel.TemplateApplied += TopLevelOnTemplateApplied; + var adorner = topLevel.FindDescendantOfType()?.AdornerLayer; + if (adorner is not null) { - adornerLayer.Children.Remove(this); + adorner.Children.Add(this); + AdornerLayer.SetAdornedElement(this, adorner); } - - // Try to get the host. If host was null, use the TopLevel instead. - var host = Host ?? Parent as Visual; - - if (host is null) throw new InvalidOperationException("NotificationControl cannot be installed. Host was not found."); - - adornerLayer = host is TopLevel - ? host.FindDescendantOfType()?.AdornerLayer - : AdornerLayer.GetAdornerLayer(host); + } - if (adornerLayer is not null) + private void TopLevelOnTemplateApplied(object? sender, TemplateAppliedEventArgs e) + { + if (Parent is AdornerLayer adornerLayer) { - adornerLayer.Children.Add(this); - AdornerLayer.SetAdornedElement(this, adornerLayer); + adornerLayer.Children.Remove(this); + AdornerLayer.SetAdornedElement(this, null); } + + // Reinstall notification manager on template reapplied. + var topLevel = (TopLevel)sender!; + topLevel.TemplateApplied -= TopLevelOnTemplateApplied; + InstallFromTopLevel(topLevel); } private void UpdatePseudoClasses(NotificationPosition position) diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs index 37c46e1e7d..f21b608667 100644 --- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs +++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs @@ -61,7 +61,7 @@ namespace Avalonia.Controls.Primitives return adorner.GetValue(AdornedElementProperty); } - public static void SetAdornedElement(Visual adorner, Visual adorned) + public static void SetAdornedElement(Visual adorner, Visual? adorned) { adorner.SetValue(AdornedElementProperty, adorned); }