From 89b17752f3f65343339be33b20fa47e4542bea01 Mon Sep 17 00:00:00 2001 From: Zhang Dian <54255897+zdpcdt@users.noreply.github.com> Date: Thu, 27 Mar 2025 23:36:32 +0800 Subject: [PATCH 1/3] feat: add TryGetXXManager to WindowXXManager. --- .../Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs | 10 ++++++++++ demo/Ursa.Demo/Pages/NotificationDemo.axaml.cs | 12 +++++------- demo/Ursa.Demo/ViewModels/MainViewViewModel.cs | 9 ++++++++- demo/Ursa.Demo/Views/MainView.axaml.cs | 17 +++++++++++++++++ demo/Ursa.Demo/Views/MainWindow.axaml.cs | 3 +++ .../Notification/WindowNotificationManager.cs | 7 +++++++ .../NotificationShared/WindowMessageManager.cs | 6 ++++++ src/Ursa/Controls/Toast/WindowToastManager.cs | 10 +++++++++- 8 files changed, 65 insertions(+), 9 deletions(-) diff --git a/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs b/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs index 1cbc0ce..c8353aa 100644 --- a/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs +++ b/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs @@ -1,8 +1,11 @@ +using System; using Avalonia; using Avalonia.Controls; +using Avalonia.Controls.Notifications; using Avalonia.Controls.Primitives; using Avalonia.VisualTree; using Ursa.Controls; +using WindowNotificationManager = Ursa.Controls.WindowNotificationManager; namespace Ursa.Demo.Dialogs; @@ -25,6 +28,13 @@ public partial class CustomDemoDialog : UserControl _viewModel.NotificationManager = new WindowNotificationManager(visualLayerManager) { MaxItems = 3 }; _viewModel.ToastManager = new WindowToastManager(visualLayerManager) { MaxItems = 3 }; } + + WindowNotificationManager.TryGetNotificationManager(visualLayerManager, out var manager); + if (manager is not null && _viewModel is not null) + { + Console.WriteLine(ReferenceEquals(_viewModel.NotificationManager, manager)); + manager.Position = NotificationPosition.TopCenter; + } } protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) diff --git a/demo/Ursa.Demo/Pages/NotificationDemo.axaml.cs b/demo/Ursa.Demo/Pages/NotificationDemo.axaml.cs index 31d0e78..ccdb5d0 100644 --- a/demo/Ursa.Demo/Pages/NotificationDemo.axaml.cs +++ b/demo/Ursa.Demo/Pages/NotificationDemo.axaml.cs @@ -1,6 +1,5 @@ using Avalonia; using Avalonia.Controls; -using Avalonia.LogicalTree; using Ursa.Controls; using Ursa.Demo.ViewModels; @@ -21,12 +20,11 @@ public partial class NotificationDemo : UserControl { base.OnAttachedToVisualTree(e); var topLevel = TopLevel.GetTopLevel(this); - _viewModel.NotificationManager = new WindowNotificationManager(topLevel) { MaxItems = 3 }; - } - protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) - { - base.OnDetachedFromLogicalTree(e); - _viewModel.NotificationManager?.Uninstall(); + WindowNotificationManager.TryGetNotificationManager(topLevel, out var manager); + if (manager is not null) + { + _viewModel.NotificationManager = manager; + } } } \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs index 161df53..181c82d 100644 --- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs @@ -1,16 +1,19 @@ using System; using System.Collections.ObjectModel; using Avalonia; +using Avalonia.Controls.Notifications; using Avalonia.Styling; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; -using Ursa.Controls; using Ursa.Themes.Semi; +using Notification = Ursa.Controls.Notification; +using WindowNotificationManager = Ursa.Controls.WindowNotificationManager; namespace Ursa.Demo.ViewModels; public partial class MainViewViewModel : ViewModelBase { + public WindowNotificationManager? NotificationManager { get; set; } public MenuViewModel Menus { get; set; } = new MenuViewModel(); private object? _content; @@ -107,6 +110,10 @@ public partial class MainViewViewModel : ViewModelBase if (app is not null) { app.RequestedThemeVariant = newValue.Theme; + NotificationManager?.Show( + new Notification("Theme changed", $"Theme changed to {newValue.Name}"), + type: NotificationType.Success, + classes: ["Light"]); } } diff --git a/demo/Ursa.Demo/Views/MainView.axaml.cs b/demo/Ursa.Demo/Views/MainView.axaml.cs index 8ee2660..c7353e1 100644 --- a/demo/Ursa.Demo/Views/MainView.axaml.cs +++ b/demo/Ursa.Demo/Views/MainView.axaml.cs @@ -1,11 +1,28 @@ +using Avalonia; using Avalonia.Controls; +using Ursa.Controls; +using Ursa.Demo.ViewModels; namespace Ursa.Demo.Views; public partial class MainView : UserControl { + private MainViewViewModel? _viewModel; + public MainView() { InitializeComponent(); } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + _viewModel = DataContext as MainViewViewModel; + var topLevel = TopLevel.GetTopLevel(this); + WindowNotificationManager.TryGetNotificationManager(topLevel, out var manager); + if (manager is not null && _viewModel is not null) + { + _viewModel.NotificationManager = manager; + } + } } \ No newline at end of file diff --git a/demo/Ursa.Demo/Views/MainWindow.axaml.cs b/demo/Ursa.Demo/Views/MainWindow.axaml.cs index 3edd6fe..1aa93a4 100644 --- a/demo/Ursa.Demo/Views/MainWindow.axaml.cs +++ b/demo/Ursa.Demo/Views/MainWindow.axaml.cs @@ -5,9 +5,12 @@ namespace Ursa.Demo.Views; public partial class MainWindow : UrsaWindow { + public WindowNotificationManager? NotificationManager { get; set; } + public MainWindow() { InitializeComponent(); + NotificationManager = new WindowNotificationManager(this) { MaxItems = 3 }; } protected override async Task CanClose() diff --git a/src/Ursa/Controls/Notification/WindowNotificationManager.cs b/src/Ursa/Controls/Notification/WindowNotificationManager.cs index 8b9e41e..21063ad 100644 --- a/src/Ursa/Controls/Notification/WindowNotificationManager.cs +++ b/src/Ursa/Controls/Notification/WindowNotificationManager.cs @@ -5,6 +5,7 @@ using Avalonia.Controls.Notifications; using Avalonia.Controls.Primitives; using Avalonia.Layout; using Avalonia.Threading; +using Avalonia.VisualTree; namespace Ursa.Controls; @@ -69,6 +70,12 @@ public class WindowNotificationManager : WindowMessageManager, INotificationMana VerticalAlignmentProperty.OverrideDefaultValue(VerticalAlignment.Stretch); } + public static bool TryGetNotificationManager(Visual? visual, out WindowNotificationManager? manager) + { + manager = visual?.FindDescendantOfType(); + return manager is not null; + } + /// public void Show(INotification content) { diff --git a/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs b/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs index 196566b..aa8c6d6 100644 --- a/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs +++ b/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs @@ -84,6 +84,12 @@ public abstract class WindowMessageManager : TemplatedControl } } + public static bool TryGetMessageManager(Visual? visual, out WindowMessageManager? manager) + { + manager = visual?.FindDescendantOfType(); + return manager is not null; + } + protected void TopLevelOnTemplateApplied(object? sender, TemplateAppliedEventArgs e) { if (Parent is AdornerLayer adornerLayer) diff --git a/src/Ursa/Controls/Toast/WindowToastManager.cs b/src/Ursa/Controls/Toast/WindowToastManager.cs index 312c7df..603cd5e 100644 --- a/src/Ursa/Controls/Toast/WindowToastManager.cs +++ b/src/Ursa/Controls/Toast/WindowToastManager.cs @@ -1,7 +1,9 @@ -using Avalonia.Controls; +using Avalonia; +using Avalonia.Controls; using Avalonia.Controls.Notifications; using Avalonia.Controls.Primitives; using Avalonia.Threading; +using Avalonia.VisualTree; namespace Ursa.Controls; @@ -33,6 +35,12 @@ public class WindowToastManager : WindowMessageManager, IToastManager { } + public static bool TryGetToastManager(Visual? visual, out WindowToastManager? manager) + { + manager = visual?.FindDescendantOfType(); + return manager is not null; + } + /// public void Show(IToast content) { From c2e7a217abce666309e431327d5030d0ee6ee836 Mon Sep 17 00:00:00 2001 From: Dong Bin Date: Fri, 28 Mar 2025 11:24:05 +0800 Subject: [PATCH 2/3] feat: simplify demo. --- .../Dialogs/CustomDemoDialog.axaml.cs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs b/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs index c8353aa..7e5cd07 100644 --- a/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs +++ b/demo/Ursa.Demo/Dialogs/CustomDemoDialog.axaml.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Notifications; @@ -23,24 +24,14 @@ public partial class CustomDemoDialog : UserControl base.OnAttachedToVisualTree(e); _viewModel = this.DataContext as CustomDemoDialogViewModel; var visualLayerManager = this.FindAncestorOfType(); - if (visualLayerManager is not null && _viewModel is not null) - { - _viewModel.NotificationManager = new WindowNotificationManager(visualLayerManager) { MaxItems = 3 }; - _viewModel.ToastManager = new WindowToastManager(visualLayerManager) { MaxItems = 3 }; - } - - WindowNotificationManager.TryGetNotificationManager(visualLayerManager, out var manager); - if (manager is not null && _viewModel is not null) - { - Console.WriteLine(ReferenceEquals(_viewModel.NotificationManager, manager)); - manager.Position = NotificationPosition.TopCenter; - } - } - - protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnDetachedFromVisualTree(e); - _viewModel?.NotificationManager?.Uninstall(); - _viewModel?.ToastManager?.Uninstall(); + if (_viewModel == null) return; + _viewModel.NotificationManager = + WindowNotificationManager.TryGetNotificationManager(visualLayerManager, out var notificationManager) + ? notificationManager + : new WindowNotificationManager(visualLayerManager) { MaxItems = 3 }; + _viewModel.ToastManager = WindowToastManager.TryGetToastManager(visualLayerManager, out var toastManager) + ? toastManager + : new WindowToastManager(visualLayerManager) { MaxItems = 3 }; + Debug.Assert(WindowNotificationManager.TryGetNotificationManager(visualLayerManager, out _)); } } \ No newline at end of file From ffc47f572fd5018e0b1523c106cd5b12c37c9e99 Mon Sep 17 00:00:00 2001 From: Dong Bin Date: Fri, 28 Mar 2025 11:52:23 +0800 Subject: [PATCH 3/3] misc: update comment. --- src/Ursa/Controls/Notification/WindowNotificationManager.cs | 6 ++++++ .../Controls/NotificationShared/WindowMessageManager.cs | 6 ------ src/Ursa/Controls/Toast/WindowToastManager.cs | 6 ++++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Ursa/Controls/Notification/WindowNotificationManager.cs b/src/Ursa/Controls/Notification/WindowNotificationManager.cs index 21063ad..3613076 100644 --- a/src/Ursa/Controls/Notification/WindowNotificationManager.cs +++ b/src/Ursa/Controls/Notification/WindowNotificationManager.cs @@ -70,6 +70,12 @@ public class WindowNotificationManager : WindowMessageManager, INotificationMana VerticalAlignmentProperty.OverrideDefaultValue(VerticalAlignment.Stretch); } + /// + /// Tries to get the from a . + /// + /// A that is either a or a . + /// The existing if found, or null if not found. + /// True if a is found; otherwise, false. public static bool TryGetNotificationManager(Visual? visual, out WindowNotificationManager? manager) { manager = visual?.FindDescendantOfType(); diff --git a/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs b/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs index aa8c6d6..196566b 100644 --- a/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs +++ b/src/Ursa/Controls/NotificationShared/WindowMessageManager.cs @@ -84,12 +84,6 @@ public abstract class WindowMessageManager : TemplatedControl } } - public static bool TryGetMessageManager(Visual? visual, out WindowMessageManager? manager) - { - manager = visual?.FindDescendantOfType(); - return manager is not null; - } - protected void TopLevelOnTemplateApplied(object? sender, TemplateAppliedEventArgs e) { if (Parent is AdornerLayer adornerLayer) diff --git a/src/Ursa/Controls/Toast/WindowToastManager.cs b/src/Ursa/Controls/Toast/WindowToastManager.cs index 603cd5e..a2b037a 100644 --- a/src/Ursa/Controls/Toast/WindowToastManager.cs +++ b/src/Ursa/Controls/Toast/WindowToastManager.cs @@ -35,6 +35,12 @@ public class WindowToastManager : WindowMessageManager, IToastManager { } + /// + /// Tries to get the from a or . + /// + /// A that is either a or a . + /// The existing if found, or null if not found. + /// True if a is found; otherwise, false. public static bool TryGetToastManager(Visual? visual, out WindowToastManager? manager) { manager = visual?.FindDescendantOfType();