Dan Walmsley преди 6 години
родител
ревизия
e45805aa50

+ 2 - 2
samples/ControlCatalog/MainWindow.xaml.cs

@@ -12,7 +12,7 @@ namespace ControlCatalog
 {
     public class MainWindow : Window
     {
-        private NotificationArea _notificationArea;
+        private WindowNotificationManager _notificationArea;
 
         public MainWindow()
         {
@@ -21,7 +21,7 @@ namespace ControlCatalog
             //Renderer.DrawFps = true;
             //Renderer.DrawDirtyRects = Renderer.DrawFps = true;
 
-            _notificationArea = new NotificationArea
+            _notificationArea = new WindowNotificationManager
             {
                 Position = NotificationPosition.TopRight,
                 MaxItems = 3

+ 6 - 8
samples/ControlCatalog/ViewModels/MainWindowViewModel.cs

@@ -1,15 +1,15 @@
 using System.Reactive;
-using System.Threading.Tasks;
 using Avalonia.Controls.Notifications;
 using Avalonia.Diagnostics.ViewModels;
-using Avalonia.Threading;
 using ReactiveUI;
 
 namespace ControlCatalog.ViewModels
 {
     class MainWindowViewModel : ViewModelBase
     {
-        public MainWindowViewModel(INotificationManager notificationManager)
+        private IManagedNotificationManager _notificationManager;
+
+        public MainWindowViewModel(IManagedNotificationManager notificationManager)
         {
             _notificationManager = notificationManager;
 
@@ -20,18 +20,16 @@ namespace ControlCatalog.ViewModels
 
             ShowManagedNotificationCommand = ReactiveCommand.Create(() =>
             {
-                NotificationManager.Show(new NotificationContent { Title = "Welcome", Message = "Avalonia now supports Notifications.", Type = NotificationType.Information });
+                NotificationManager.Show(SimpleNotification.Create("Welcome", "Avalonia now supports Notifications.",  NotificationType.Information));
             });
 
             ShowNativeNotificationCommand = ReactiveCommand.Create(() =>
             {
-                NotificationManager.Show(new NotificationContent { Title = "Error", Message = "Native Notifications are not quite ready. Coming soon.", Type = NotificationType.Error });
+                NotificationManager.Show(SimpleNotification.Create("Error", "Native Notifications are not quite ready. Coming soon.", NotificationType.Error));
             });
         }
 
-        private INotificationManager _notificationManager;
-
-        public INotificationManager NotificationManager
+        public IManagedNotificationManager NotificationManager
         {
             get { return _notificationManager; }
             set { this.RaiseAndSetIfChanged(ref _notificationManager, value); }

+ 2 - 3
samples/ControlCatalog/ViewModels/NotificationViewModel.cs

@@ -1,5 +1,4 @@
 using System.Reactive;
-using Avalonia;
 using Avalonia.Controls.Notifications;
 using ReactiveUI;
 
@@ -11,12 +10,12 @@ namespace ControlCatalog.ViewModels
         {
             YesCommand = ReactiveCommand.Create(() =>
             {
-                manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today." });
+                manager.Show(SimpleNotification.Create("Avalonia Notifications", "Start adding notifications to your app today."));
             });
 
             NoCommand = ReactiveCommand.Create(() =>
             {
-                manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today. To find out more visit..." });
+                manager.Show(SimpleNotification.Create("Avalonia Notifications", "Start adding notifications to your app today. To find out more visit..."));
             });
         }
 

+ 20 - 2
src/Avalonia.Controls/Notifications/INotificationManager.cs

@@ -2,10 +2,28 @@
 
 namespace Avalonia.Controls.Notifications
 {
+    public interface INotification
+    {
+        string Title { get; }
+
+        string Message { get; }
+
+        NotificationType Type { get; }
+
+        TimeSpan Expiration { get; }
+
+        Action OnClick { get; }
+
+        Action OnClose { get; }
+    }
+
     public interface INotificationManager
     {
-        void Show(object content, TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null);
+        void Show(INotification notification);
+    }
 
-        void Show(NotificationContent content, TimeSpan? expirationTime = null, Action onClick = null, Action onClose = null);
+    public interface IManagedNotificationManager : INotificationManager
+    {
+        void Show(object content);
     }
 }

+ 1 - 1
src/Avalonia.Controls/Notifications/Notification.cs

@@ -20,7 +20,7 @@ namespace Avalonia.Controls.Notifications
         public Notification()
         {
             this.GetObservable(ContentProperty)
-                .OfType<NotificationContent>()
+                .OfType<SimpleNotification>()
                 .Subscribe(x =>
                 {
                     switch (x.Type)

+ 0 - 27
src/Avalonia.Controls/Notifications/NotificationContent.cs

@@ -1,27 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Avalonia.Controls.Notifications
-{
-    /// <summary>
-    /// Defines content for a <see cref="Notification"/> control.
-    /// </summary>
-    /// <remarks>
-    /// This notification content type is compatible with native notifications.
-    /// </remarks>
-    public class NotificationContent
-    {
-        public string Title { get; set; }
-        public string Message { get; set; }
-        public NotificationType Type { get; set; }
-    }
-
-    public enum NotificationType
-    {
-        Information,
-        Success,
-        Warning,
-        Error
-    }
-}

+ 56 - 0
src/Avalonia.Controls/Notifications/SimpleNotification.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Avalonia.Controls.Notifications
+{
+    /// <summary>
+    /// Defines content for a <see cref="Notification"/> control.
+    /// </summary>
+    /// <remarks>
+    /// This notification content type is compatible with native notifications.
+    /// </remarks>
+    public class SimpleNotification : INotification
+    {
+        public static INotification Create (
+            string title, 
+            string message, 
+            NotificationType type = NotificationType.Information, 
+            TimeSpan? expiration = null, 
+            Action onClick = null, 
+            Action onClose = null)
+        {
+            var result = new SimpleNotification
+            {
+                Title = title,
+                Message = message,
+                Type = type,
+                Expiration = expiration.HasValue ? expiration.Value : TimeSpan.FromSeconds(5),
+                OnClick = onClick,
+                OnClose = onClose
+            };
+
+            return result;
+        }
+
+        public string Title { get; private set; }
+
+        public string Message { get; private set; }
+
+        public NotificationType Type { get; private set; }
+
+        public TimeSpan Expiration { get; private set; }
+
+        public Action OnClick { get; private set; }
+
+        public Action OnClose { get; private set; }
+    }
+
+    public enum NotificationType
+    {
+        Information,
+        Success,
+        Warning,
+        Error
+    }
+}

+ 31 - 24
src/Avalonia.Controls/Notifications/NotificationArea.cs → src/Avalonia.Controls/Notifications/WindowNotificationManager.cs

@@ -8,7 +8,7 @@ using Avalonia.VisualTree;
 
 namespace Avalonia.Controls.Notifications
 {
-    public class NotificationArea : TemplatedControl, INotificationManager
+    public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager
     {
         private IList _items;
 
@@ -23,7 +23,7 @@ namespace Avalonia.Controls.Notifications
         }
 
         public static readonly AvaloniaProperty<NotificationPosition> PositionProperty =
-          AvaloniaProperty.RegisterAttached<NotificationArea, TopLevel, NotificationPosition>("Position", defaultValue: NotificationPosition.TopLeft, inherits: true);
+          AvaloniaProperty.RegisterAttached<WindowNotificationManager, TopLevel, NotificationPosition>("Position", defaultValue: NotificationPosition.TopLeft, inherits: true);
 
         public NotificationPosition Position
         {
@@ -42,7 +42,7 @@ namespace Avalonia.Controls.Notifications
         }
 
         public static readonly AvaloniaProperty<int> MaxItemsProperty =
-          AvaloniaProperty.RegisterAttached<NotificationArea, TopLevel, int>("Position", defaultValue: 5, inherits: true);
+          AvaloniaProperty.RegisterAttached<WindowNotificationManager, TopLevel, int>("Position", defaultValue: 5, inherits: true);
 
         public int MaxItems
         {
@@ -50,15 +50,15 @@ namespace Avalonia.Controls.Notifications
             set { SetValue(MaxItemsProperty, value); }
         }
 
-        static NotificationArea()
+        static WindowNotificationManager()
         {
-            PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopLeft, ":topleft");
-            PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopRight, ":topright");
-            PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomLeft, ":bottomleft");
-            PseudoClass<NotificationArea, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomRight, ":bottomright");
+            PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopLeft, ":topleft");
+            PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.TopRight, ":topright");
+            PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomLeft, ":bottomleft");
+            PseudoClass<WindowNotificationManager, NotificationPosition>(PositionProperty, x => x == NotificationPosition.BottomRight, ":bottomright");
 
-            HorizontalAlignmentProperty.OverrideDefaultValue<NotificationArea>(Layout.HorizontalAlignment.Stretch);
-            VerticalAlignmentProperty.OverrideDefaultValue<NotificationArea>(Layout.VerticalAlignment.Stretch);
+            HorizontalAlignmentProperty.OverrideDefaultValue<WindowNotificationManager>(Layout.HorizontalAlignment.Stretch);
+            VerticalAlignmentProperty.OverrideDefaultValue<WindowNotificationManager>(Layout.VerticalAlignment.Stretch);
         }
 
         protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
@@ -69,32 +69,39 @@ namespace Avalonia.Controls.Notifications
             _items = itemsControl?.Children;
         }
 
-        public void Show(NotificationContent content, TimeSpan? expirationTime, Action onClick, Action onClose)
+        public void Show(INotification content)
         {
-            Show(content as object, expirationTime, onClick, onClose);
+            Show(content as object);
         }
 
-        public async void Show(object content, TimeSpan? expirationTime, Action onClick, Action onClose)
+        public async void Show(object content)
         {
-            var notification = new Notification
+            var notification = content as INotification;
+
+            var notificationControl = new Notification
             {
                 Content = content
             };
 
-            notification.PointerPressed += (sender, args) =>
+            if (notification != null)
+            {
+                notificationControl.NotificationClosed += (sender, args) => notification.OnClose?.Invoke();
+            }
+
+            notificationControl.NotificationClosed += OnNotificationClosed;
+
+            notificationControl.PointerPressed += (sender, args) =>
             {
-                if (onClick != null)
+                if (notification != null && notification.OnClick != null)
                 {
-                    onClick.Invoke();
+                    notification.OnClick.Invoke();
                     (sender as Notification)?.Close();
                 }
             };
-            notification.NotificationClosed += (sender, args) => onClose?.Invoke();
-            notification.NotificationClosed += OnNotificationClosed;
 
             lock (_items)
             {
-                _items.Add(notification);
+                _items.Add(notificationControl);
 
                 if (_items.OfType<Notification>().Count(i => !i.IsClosing) > MaxItems)
                 {
@@ -102,14 +109,14 @@ namespace Avalonia.Controls.Notifications
                 }
             }
 
-            if (expirationTime == TimeSpan.MaxValue)
+            if (notification != null && notification.Expiration == TimeSpan.MaxValue)
             {
                 return;
             }
 
-            await Task.Delay(expirationTime ?? TimeSpan.FromSeconds(5));
+            await Task.Delay(notification?.Expiration ?? TimeSpan.FromSeconds(5));
 
-            notification.Close();
+            notificationControl.Close();
         }
 
         private void OnNotificationClosed(object sender, RoutedEventArgs routedEventArgs)
@@ -118,7 +125,7 @@ namespace Avalonia.Controls.Notifications
             _items.Remove(notification);
         }
 
-        public void Install(TopLevel host)
+        public void Install(Window host)
         {
             var adornerLayer = host.GetVisualDescendants()
                 .OfType<AdornerDecorator>()

+ 5 - 0
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@@ -26,4 +26,9 @@
       <Generator>MSBuild:Compile</Generator>
     </EmbeddedResource>
   </ItemGroup>
+  <ItemGroup>
+    <None Update="WindowNotificationManager.xaml">
+      <Generator>MSBuild:Compile</Generator>
+    </None>
+  </ItemGroup>
 </Project>

+ 1 - 1
src/Avalonia.Themes.Default/DefaultTheme.xaml

@@ -46,5 +46,5 @@
   <StyleInclude Source="resm:Avalonia.Themes.Default.ButtonSpinner.xaml?assembly=Avalonia.Themes.Default"/>
   <StyleInclude Source="resm:Avalonia.Themes.Default.NumericUpDown.xaml?assembly=Avalonia.Themes.Default"/>
   <StyleInclude Source="resm:Avalonia.Themes.Default.AutoCompleteBox.xaml?assembly=Avalonia.Themes.Default"/>
-  <StyleInclude Source="resm:Avalonia.Themes.Default.NotificationArea.xaml?assembly=Avalonia.Themes.Default"/>
+  <StyleInclude Source="resm:Avalonia.Themes.Default.WindowNotificationManager.xaml?assembly=Avalonia.Themes.Default"/>
 </Styles>

+ 6 - 6
src/Avalonia.Themes.Default/NotificationArea.xaml → src/Avalonia.Themes.Default/WindowNotificationManager.xaml

@@ -1,12 +1,12 @@
 <Styles xmlns="https://github.com/avaloniaui"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
-    <Style Selector="NotificationArea">
+    <Style Selector="WindowNotificationManager">
         <Setter Property="Margin" Value="0 0 8 8"/>
         <Setter Property="Template">
             <ControlTemplate>
                 <StackPanel Name="PART_Items">
                     <StackPanel.DataTemplates>
-                        <DataTemplate DataType="NotificationContent">
+                        <DataTemplate DataType="INotification">
                             <StackPanel Spacing="8" Margin="12">
                                 <TextBlock DockPanel.Dock="Top" Text="{Binding Title}" FontWeight="Medium" />
                                 <TextBlock MaxHeight="80" Text="{Binding Message}" TextWrapping="Wrap" Margin="0,0,12,0"/>
@@ -119,23 +119,23 @@
         <Setter Property="Background" Value="OrangeRed"/>
     </Style>
 
-    <Style Selector="NotificationArea:topleft /template/ StackPanel#PART_Items">
+    <Style Selector="WindowNotificationManager:topleft /template/ StackPanel#PART_Items">
         <Setter Property="VerticalAlignment" Value="Top"/>
         <Setter Property="HorizontalAlignment" Value="Left"/>
     </Style>
 
-    <Style Selector="NotificationArea:topright /template/ StackPanel#PART_Items">
+    <Style Selector="WindowNotificationManager:topright /template/ StackPanel#PART_Items">
         <Setter Property="VerticalAlignment" Value="Top"/>
         <Setter Property="HorizontalAlignment" Value="Right"/>
     </Style>
 
-    <Style Selector="NotificationArea:bottomleft /template/ StackPanel#PART_Items">
+    <Style Selector="WindowNotificationManager:bottomleft /template/ StackPanel#PART_Items">
         <Setter Property="ReverseOrder" Value="True"/>
         <Setter Property="VerticalAlignment" Value="Bottom"/>
         <Setter Property="HorizontalAlignment" Value="Left"/>
     </Style>
 
-    <Style Selector="NotificationArea:bottomright /template/ StackPanel#PART_Items">
+    <Style Selector="WindowNotificationManager:bottomright /template/ StackPanel#PART_Items">
         <Setter Property="ReverseOrder" Value="True"/>
         <Setter Property="VerticalAlignment" Value="Bottom"/>
         <Setter Property="HorizontalAlignment" Value="Right"/>