diff --git a/Documentation.md b/Documentation.md index c7b20df..74c3b2f 100644 --- a/Documentation.md +++ b/Documentation.md @@ -210,7 +210,24 @@ Will work when will start new message stack. //If messages count in overlay window will be more that maximum - progress bar will start collapsed (progress bar never closing automatically) NotificationConstants.CollapseProgressIfMoreRows = true; ``` - + +- For `Absolute` message position: +Set Message position as `Absolute`, and set `NotificationConstants.AbsolutePosition` + +but, You must set base corner for position margin. + +Sample: +``` +NotificationConstants.AbsolutePosition.X = 50D; +NotificationConstants.AbsolutePosition.Y = 100D; +NotificationConstants.AbsolutePosition.BaseCorner= Corner.TopRight; +``` + +- Reverse message stack +Decide what message will be from above +Use `NotificationConstants.IsReversedPanel` to change stack orientation. Set as `null to default`. + +

diff --git a/Notification.Wpf/Base/NotificationsOverlayWindow.xaml b/Notification.Wpf/Base/NotificationsOverlayWindow.xaml index e055e71..0adfc85 100644 --- a/Notification.Wpf/Base/NotificationsOverlayWindow.xaml +++ b/Notification.Wpf/Base/NotificationsOverlayWindow.xaml @@ -14,9 +14,10 @@ ShowActivated="False" WindowStartupLocation ="CenterScreen" d:DesignWidth="900" - d:DesignHeight="600"> - + d:DesignHeight="600" + > + diff --git a/Notification.Wpf/Classes/AbsolutePosition.cs b/Notification.Wpf/Classes/AbsolutePosition.cs new file mode 100644 index 0000000..cb1d9f6 --- /dev/null +++ b/Notification.Wpf/Classes/AbsolutePosition.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Notification.Wpf.Classes +{ + /// Are absolute position + public class AbsolutePosition + { + /// X position + public double X { get; set; } + /// Y position + public double Y { get; set; } + + /// Base corner + public Corner BaseCorner { get; set; } + + /// position + public Thickness Margin => BaseCorner switch + { + Corner.TopLeft => new Thickness(X, Y, 0, 0), + Corner.TopRight => new Thickness(0, Y, X, 0), + Corner.BottomLeft => new Thickness(X, 0, 0, Y), + Corner.BottomRight => new Thickness(0, 0, X, Y), + _ => throw new ArgumentOutOfRangeException() + }; + /// Horizontal Alignment + public HorizontalAlignment HorAlign => BaseCorner switch + { + Corner.TopLeft => HorizontalAlignment.Left, + Corner.TopRight => HorizontalAlignment.Right, + Corner.BottomLeft => HorizontalAlignment.Left, + Corner.BottomRight => HorizontalAlignment.Right, + _ => throw new ArgumentOutOfRangeException() + }; + /// Horizontal Alignment + public VerticalAlignment VertAlign => BaseCorner switch + { + Corner.TopLeft => VerticalAlignment.Top, + Corner.TopRight => VerticalAlignment.Top, + Corner.BottomLeft => VerticalAlignment.Bottom, + Corner.BottomRight => VerticalAlignment.Bottom, + _ => throw new ArgumentOutOfRangeException() + }; + + } +} diff --git a/Notification.Wpf/Classes/Enums/Corner.cs b/Notification.Wpf/Classes/Enums/Corner.cs new file mode 100644 index 0000000..2bea26e --- /dev/null +++ b/Notification.Wpf/Classes/Enums/Corner.cs @@ -0,0 +1,10 @@ +namespace Notification.Wpf; + +/// corners in window +public enum Corner +{ + TopLeft, + TopRight, + BottomLeft, + BottomRight +} \ No newline at end of file diff --git a/Notification.Wpf/Constants/NotificationConstants.cs b/Notification.Wpf/Constants/NotificationConstants.cs index dc1ca8d..5df27c6 100644 --- a/Notification.Wpf/Constants/NotificationConstants.cs +++ b/Notification.Wpf/Constants/NotificationConstants.cs @@ -1,6 +1,7 @@ using System.Windows; using System.Windows.Media; using Notification.Wpf.Base; +using Notification.Wpf.Classes; using Notification.Wpf.Controls; // ReSharper disable FieldCanBeMadeReadOnly.Global @@ -18,6 +19,12 @@ public class NotificationConstants /// Overlay message position public static NotificationPosition MessagePosition { get; set; } = NotificationPosition.BottomRight; + /// Reverse are when absolute + public static bool? IsReversedPanel { get; set; } + + /// Default message position when position absolute + public static AbsolutePosition AbsolutePosition { get; } = new AbsolutePosition(); + #region Notification #region Default colors @@ -154,5 +161,11 @@ public class NotificationConstants public static object DefaultProgressButtonContent { get; set; } = "Cancel"; #endregion + + /// work area height + public static double AreaHeight => SystemParameters.WorkArea.Height; + /// work area width + public static double AreaWidth => SystemParameters.WorkArea.Width; + } } diff --git a/Notification.Wpf/Controls/NotificationArea.cs b/Notification.Wpf/Controls/NotificationArea.cs index 72b7579..80bb76e 100644 --- a/Notification.Wpf/Controls/NotificationArea.cs +++ b/Notification.Wpf/Controls/NotificationArea.cs @@ -4,8 +4,11 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Media; + using Notification.Wpf.Constants; using Notification.Wpf.View; + using Notifications.Wpf.ViewModels; namespace Notification.Wpf.Controls @@ -27,16 +30,34 @@ public class NotificationArea : Control #endregion + //public NotificationPosition Position + //{ + // get => (NotificationPosition)GetValue(PositionProperty); + // set => SetValue(PositionProperty, value); + //} + + //// Using a DependencyProperty as the backing store for Position. This enables animation, styling, binding, etc... + //public static readonly DependencyProperty PositionProperty = + // DependencyProperty.Register("Position", typeof(NotificationPosition), typeof(NotificationArea), new PropertyMetadata(NotificationPosition.BottomRight)); + + #region Position : NotificationPosition - Area position on overlay window + + /// Area position on overlay window + public static readonly DependencyProperty PositionProperty = + DependencyProperty.Register( + nameof(Position), + typeof(NotificationPosition), + typeof(NotificationArea), + new PropertyMetadata(NotificationPosition.BottomRight)); + + /// Area position on overlay window public NotificationPosition Position { get => (NotificationPosition)GetValue(PositionProperty); set => SetValue(PositionProperty, value); } - // Using a DependencyProperty as the backing store for Position. This enables animation, styling, binding, etc... - public static readonly DependencyProperty PositionProperty = - DependencyProperty.Register("Position", typeof(NotificationPosition), typeof(NotificationArea), new PropertyMetadata(NotificationPosition.BottomRight)); - + #endregion public int MaxItems { @@ -47,6 +68,21 @@ public int MaxItems public static readonly DependencyProperty MaxItemsProperty = DependencyProperty.Register("MaxItems", typeof(int), typeof(NotificationArea), new PropertyMetadata(int.MaxValue)); + #region IsReversed : bool - Are is reversed + + /// Are is reversed + public static readonly DependencyProperty IsReversedProperty = + DependencyProperty.Register( + nameof(IsReversed), + typeof(bool), + typeof(NotificationArea), + new PropertyMetadata(default(bool))); + + /// Are is reversed + public bool IsReversed { get => (bool)GetValue(IsReversedProperty); set => SetValue(IsReversedProperty, value); } + + #endregion + private IList _items; public NotificationArea() @@ -65,6 +101,9 @@ public override void OnApplyTemplate() base.OnApplyTemplate(); var itemsControl = GetTemplateChild("PART_Items") as Panel; _items = itemsControl?.Children; + + IsReversed = NotificationConstants.IsReversedPanel is { } reverse ? reverse + : Position is NotificationPosition.BottomCenter or NotificationPosition.BottomLeft or NotificationPosition.BottomRight; } #if NET40 diff --git a/Notification.Wpf/Controls/NotificationPosition.cs b/Notification.Wpf/Controls/NotificationPosition.cs index b905fcf..de11837 100644 --- a/Notification.Wpf/Controls/NotificationPosition.cs +++ b/Notification.Wpf/Controls/NotificationPosition.cs @@ -10,6 +10,7 @@ public enum NotificationPosition BottomCenter, CenterLeft, CenterRight, - Center + Center, + Absolute } } \ No newline at end of file diff --git a/Notification.Wpf/Extensions/Taskbar.cs b/Notification.Wpf/Extensions/Taskbar.cs new file mode 100644 index 0000000..af11f55 --- /dev/null +++ b/Notification.Wpf/Extensions/Taskbar.cs @@ -0,0 +1,192 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms +{ + internal enum TaskbarPosition + { + Unknown = -1, + Left, + Top, + Right, + Bottom, + } + + internal static class Taskbar + { + private enum ABS + { + AutoHide = 0x01, + AlwaysOnTop = 0x02, + } + + ////private enum ABE : uint + private enum AppBarEdge : uint + { + Left = 0, + Top = 1, + Right = 2, + Bottom = 3 + } + + ////private enum ABM : uint + private enum AppBarMessage : uint + { + New = 0x00000000, + Remove = 0x00000001, + QueryPos = 0x00000002, + SetPos = 0x00000003, + GetState = 0x00000004, + GetTaskbarPos = 0x00000005, + Activate = 0x00000006, + GetAutoHideBar = 0x00000007, + SetAutoHideBar = 0x00000008, + WindowPosChanged = 0x00000009, + SetState = 0x0000000A, + } + + private const string ClassName = "Shell_TrayWnd"; + private static APPBARDATA _appBarData; + + /// Static initializer of the class. + static Taskbar() + { + _appBarData = new APPBARDATA + { + cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)), + hWnd = FindWindow(Taskbar.ClassName, null) + }; + } + + /// + /// Gets a value indicating whether the taskbar is always on top of other windows. + /// + /// true if the taskbar is always on top of other windows; otherwise, false. + /// This property always returns false on Windows 7 and newer. + public static bool AlwaysOnTop + { + get + { + int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); + return ((ABS)state).HasFlag(ABS.AlwaysOnTop); + } + } + + /// + /// Gets a value indicating whether the taskbar is automatically hidden when inactive. + /// + /// true if the taskbar is set to auto-hide is enabled; otherwise, false. + public static bool AutoHide + { + get + { + int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); + return ((ABS)state).HasFlag(ABS.AutoHide); + } + } + + /// Gets the current display bounds of the taskbar. + public static Rectangle CurrentBounds + { + get + { + var rect = new RECT(); + if (GetWindowRect(Handle, ref rect)) + return Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom); + + return Rectangle.Empty; + } + } + + /// Gets the display bounds when the taskbar is fully visible. + public static Rectangle DisplayBounds + { + get + { + if (RefreshBoundsAndPosition()) + return Rectangle.FromLTRB(_appBarData.rect.Left, + _appBarData.rect.Top, + _appBarData.rect.Right, + _appBarData.rect.Bottom); + + return CurrentBounds; + } + } + + /// Gets the taskbar's window handle. + public static IntPtr Handle + { + get { return _appBarData.hWnd; } + } + + /// Gets the taskbar's position on the screen. + public static TaskbarPosition Position + { + get + { + if (RefreshBoundsAndPosition()) + return (TaskbarPosition)_appBarData.uEdge; + + return TaskbarPosition.Unknown; + } + } + + /// Hides the taskbar. + public static void Hide() + { + const int SW_HIDE = 0; + ShowWindow(Handle, SW_HIDE); + } + + /// Shows the taskbar. + public static void Show() + { + const int SW_SHOW = 1; + ShowWindow(Handle, SW_SHOW); + } + + private static bool RefreshBoundsAndPosition() + { + //! SHAppBarMessage returns IntPtr.Zero **if it fails** + return SHAppBarMessage(AppBarMessage.GetTaskbarPos, ref _appBarData) != IntPtr.Zero; + } + + #region DllImports + + [DllImport("user32.dll", SetLastError = true)] + private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); + + [DllImport("shell32.dll", SetLastError = true)] + private static extern IntPtr SHAppBarMessage(AppBarMessage dwMessage, [In] ref APPBARDATA pData); + + [DllImport("user32.dll")] + private static extern int ShowWindow(IntPtr hwnd, int command); + + #endregion DllImports + + [StructLayout(LayoutKind.Sequential)] + private struct APPBARDATA + { + public uint cbSize; + public IntPtr hWnd; + public uint uCallbackMessage; + public AppBarEdge uEdge; + public RECT rect; + public int lParam; + } + + [StructLayout(LayoutKind.Sequential)] + private struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + } +} \ No newline at end of file diff --git a/Notification.Wpf/Notification.Wpf.csproj b/Notification.Wpf/Notification.Wpf.csproj index 74b033d..553c2da 100644 --- a/Notification.Wpf/Notification.Wpf.csproj +++ b/Notification.Wpf/Notification.Wpf.csproj @@ -4,7 +4,7 @@ net6.0-windows;net5.0-windows;netcoreapp3.1-windows;net4.6-windows;net4.6.1-windows;net4.7-windows;net4.8-windows true latest - 6.0.0.0 + 6.1.0.0 true Notifications.Wpf.snk false @@ -31,8 +31,9 @@ https://github.com/Platonenkov/Notification.Wpf Toast Notifications WPF - Added net 6 supporting - + Added stack orientation control with constant setting: `NotificationConstants.IsReversedPanel`; + Added Message position as Absolute with constant setting: `NotificationConstants.AbsolutePosition`; + false diff --git a/Notification.Wpf/Themes/Generic.xaml b/Notification.Wpf/Themes/Generic.xaml index eb172d9..a60a824 100644 --- a/Notification.Wpf/Themes/Generic.xaml +++ b/Notification.Wpf/Themes/Generic.xaml @@ -443,8 +443,8 @@ - - + + @@ -472,12 +472,10 @@ - - @@ -485,6 +483,14 @@ + + + + + diff --git a/Notifications.Wpf.Sample/Helpers/PositionConverter.cs b/Notifications.Wpf.Sample/Helpers/PositionConverter.cs index 1f20410..daeff7a 100644 --- a/Notifications.Wpf.Sample/Helpers/PositionConverter.cs +++ b/Notifications.Wpf.Sample/Helpers/PositionConverter.cs @@ -4,6 +4,8 @@ using System.Windows.Data; using System.Windows.Markup; using MathCore.WPF.Converters; +using Notification.Wpf.Classes; +using Notification.Wpf.Constants; using Notification.Wpf.Controls; namespace Notification.Wpf.Sample.Helpers @@ -26,6 +28,7 @@ protected override object Convert(object v, Type t, object p, CultureInfo c) NotificationPosition.Center => VerticalAlignment.Center, NotificationPosition.CenterLeft => VerticalAlignment.Center, NotificationPosition.CenterRight => VerticalAlignment.Center, + NotificationPosition.Absolute=>NotificationConstants.AbsolutePosition.VertAlign, _ => throw new ArgumentOutOfRangeException() }; } @@ -52,11 +55,64 @@ protected override object Convert(object v, Type t, object p, CultureInfo c) NotificationPosition.Center => HorizontalAlignment.Center, NotificationPosition.CenterLeft => HorizontalAlignment.Left, NotificationPosition.CenterRight => HorizontalAlignment.Right, + NotificationPosition.Absolute => NotificationConstants.AbsolutePosition.HorAlign, _ => throw new ArgumentOutOfRangeException() }; } protected override object ConvertBack(object v, Type t, object p, CultureInfo c) => throw new NotSupportedException(); + } + [ValueConversion(typeof(NotificationPosition), typeof(bool)), MarkupExtensionReturnType(typeof(AbsolutePositionConverter))] + internal class AbsolutePositionConverter : ValueConverter + { + protected override object Convert(object v, Type t, object p, CultureInfo c) + { + if (v is not NotificationPosition pos) + return Binding.DoNothing; + return pos == NotificationPosition.Absolute; + } + + protected override object ConvertBack(object v, Type t, object p, CultureInfo c) => throw new NotSupportedException(); + + } + [ValueConversion(typeof(AbsolutePosition), typeof(Thickness)), MarkupExtensionReturnType(typeof(CornerPositionMarginConverter))] + internal class CornerPositionMarginConverter : ValueConverter + { + protected override object Convert(object v, Type t, object p, CultureInfo c) + { + if (v is not AbsolutePosition pos) + return Binding.DoNothing; + return pos.Margin; + } + + protected override object ConvertBack(object v, Type t, object p, CultureInfo c) => throw new NotSupportedException(); + + } + [ValueConversion(typeof(AbsolutePosition), typeof(HorizontalAlignment)), MarkupExtensionReturnType(typeof(CornerPositionHorAlignConverter))] + internal class CornerPositionHorAlignConverter : ValueConverter + { + protected override object Convert(object v, Type t, object p, CultureInfo c) + { + if (v is not AbsolutePosition pos) + return Binding.DoNothing; + return pos.HorAlign; + } + + protected override object ConvertBack(object v, Type t, object p, CultureInfo c) => throw new NotSupportedException(); + + } + [ValueConversion(typeof(AbsolutePosition), typeof(VerticalAlignment)), MarkupExtensionReturnType(typeof(CornerPositionVertAlignConverter))] + internal class CornerPositionVertAlignConverter : ValueConverter + { + protected override object Convert(object v, Type t, object p, CultureInfo c) + { + if (v is not AbsolutePosition pos) + return Binding.DoNothing; + return pos.VertAlign; + } + + protected override object ConvertBack(object v, Type t, object p, CultureInfo c) => throw new NotSupportedException(); + } } diff --git a/Notifications.Wpf.Sample/Helpers/Taskbar.cs b/Notifications.Wpf.Sample/Helpers/Taskbar.cs new file mode 100644 index 0000000..af11f55 --- /dev/null +++ b/Notifications.Wpf.Sample/Helpers/Taskbar.cs @@ -0,0 +1,192 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace System.Windows.Forms +{ + internal enum TaskbarPosition + { + Unknown = -1, + Left, + Top, + Right, + Bottom, + } + + internal static class Taskbar + { + private enum ABS + { + AutoHide = 0x01, + AlwaysOnTop = 0x02, + } + + ////private enum ABE : uint + private enum AppBarEdge : uint + { + Left = 0, + Top = 1, + Right = 2, + Bottom = 3 + } + + ////private enum ABM : uint + private enum AppBarMessage : uint + { + New = 0x00000000, + Remove = 0x00000001, + QueryPos = 0x00000002, + SetPos = 0x00000003, + GetState = 0x00000004, + GetTaskbarPos = 0x00000005, + Activate = 0x00000006, + GetAutoHideBar = 0x00000007, + SetAutoHideBar = 0x00000008, + WindowPosChanged = 0x00000009, + SetState = 0x0000000A, + } + + private const string ClassName = "Shell_TrayWnd"; + private static APPBARDATA _appBarData; + + /// Static initializer of the class. + static Taskbar() + { + _appBarData = new APPBARDATA + { + cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)), + hWnd = FindWindow(Taskbar.ClassName, null) + }; + } + + /// + /// Gets a value indicating whether the taskbar is always on top of other windows. + /// + /// true if the taskbar is always on top of other windows; otherwise, false. + /// This property always returns false on Windows 7 and newer. + public static bool AlwaysOnTop + { + get + { + int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); + return ((ABS)state).HasFlag(ABS.AlwaysOnTop); + } + } + + /// + /// Gets a value indicating whether the taskbar is automatically hidden when inactive. + /// + /// true if the taskbar is set to auto-hide is enabled; otherwise, false. + public static bool AutoHide + { + get + { + int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); + return ((ABS)state).HasFlag(ABS.AutoHide); + } + } + + /// Gets the current display bounds of the taskbar. + public static Rectangle CurrentBounds + { + get + { + var rect = new RECT(); + if (GetWindowRect(Handle, ref rect)) + return Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom); + + return Rectangle.Empty; + } + } + + /// Gets the display bounds when the taskbar is fully visible. + public static Rectangle DisplayBounds + { + get + { + if (RefreshBoundsAndPosition()) + return Rectangle.FromLTRB(_appBarData.rect.Left, + _appBarData.rect.Top, + _appBarData.rect.Right, + _appBarData.rect.Bottom); + + return CurrentBounds; + } + } + + /// Gets the taskbar's window handle. + public static IntPtr Handle + { + get { return _appBarData.hWnd; } + } + + /// Gets the taskbar's position on the screen. + public static TaskbarPosition Position + { + get + { + if (RefreshBoundsAndPosition()) + return (TaskbarPosition)_appBarData.uEdge; + + return TaskbarPosition.Unknown; + } + } + + /// Hides the taskbar. + public static void Hide() + { + const int SW_HIDE = 0; + ShowWindow(Handle, SW_HIDE); + } + + /// Shows the taskbar. + public static void Show() + { + const int SW_SHOW = 1; + ShowWindow(Handle, SW_SHOW); + } + + private static bool RefreshBoundsAndPosition() + { + //! SHAppBarMessage returns IntPtr.Zero **if it fails** + return SHAppBarMessage(AppBarMessage.GetTaskbarPos, ref _appBarData) != IntPtr.Zero; + } + + #region DllImports + + [DllImport("user32.dll", SetLastError = true)] + private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); + + [DllImport("shell32.dll", SetLastError = true)] + private static extern IntPtr SHAppBarMessage(AppBarMessage dwMessage, [In] ref APPBARDATA pData); + + [DllImport("user32.dll")] + private static extern int ShowWindow(IntPtr hwnd, int command); + + #endregion DllImports + + [StructLayout(LayoutKind.Sequential)] + private struct APPBARDATA + { + public uint cbSize; + public IntPtr hWnd; + public uint uCallbackMessage; + public AppBarEdge uEdge; + public RECT rect; + public int lParam; + } + + [StructLayout(LayoutKind.Sequential)] + private struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + } +} \ No newline at end of file diff --git a/Notifications.Wpf.Sample/ViewModels/SampleWindowViewModel.cs b/Notifications.Wpf.Sample/ViewModels/SampleWindowViewModel.cs index 443bd78..28cac29 100644 --- a/Notifications.Wpf.Sample/ViewModels/SampleWindowViewModel.cs +++ b/Notifications.Wpf.Sample/ViewModels/SampleWindowViewModel.cs @@ -380,6 +380,106 @@ public bool ShowInParentWindow } } + #endregion + + #region AbsoluteX : double - Point x to absolute position + + /// Point x to absolute position + private double _AbsoluteX; + + /// Point x to absolute position + public double AbsoluteX + { + get => _AbsoluteX; + set + { + Set(ref _AbsoluteX, value); + if(MessagePosition == NotificationPosition.Absolute) + { + NotificationConstants.AbsolutePosition.X = value; + AbsolutePos.X = value; + OnPropertyChanged(nameof(AbsolutePos)); + SetContent(); + } + + } + } + + #endregion + + #region AbsoluteY : double - Point Y to absolute position + + /// Point Y to absolute position + private double _AbsoluteY; + + /// Point Y to absolute position + public double AbsoluteY + { + get => _AbsoluteY; + set + { + Set(ref _AbsoluteY, value); + if (MessagePosition == NotificationPosition.Absolute) + { + NotificationConstants.AbsolutePosition.Y = value; + AbsolutePos.Y = value; + OnPropertyChanged(nameof(AbsolutePos)); + SetContent(); + } + + } + } + + #endregion + + #region IsReverse : bool - Reverse area + + /// Reverse area + private bool? _IsReverse; + + /// Reverse area + public bool? IsReverse + { + get => _IsReverse; + set + { + Set(ref _IsReverse, value); + NotificationConstants.IsReversedPanel = value; + SetContent(); + } + } + + #endregion + + #region BaseCorner : Corner - Absolute base corner + + /// Absolute base corner + private Corner _BaseCorner; + + /// Absolute base corner + public Corner BaseCorner + { + get => _BaseCorner; + set + { + Set(ref _BaseCorner, value); + NotificationConstants.AbsolutePosition.BaseCorner = value; + AbsolutePos.BaseCorner = value; + OnPropertyChanged(nameof(AbsolutePos)); + SetContent(); + } + } + + #endregion + + #region AbsolutePos : AbsolutePosition - absolute position for preview window + + /// absolute position for preview window + private AbsolutePosition _AbsolutePos = NotificationConstants.AbsolutePosition; + + /// absolute position for preview window + public AbsolutePosition AbsolutePos { get => _AbsolutePos; set => Set(ref _AbsolutePos, value); } + #endregion #endregion diff --git a/Notifications.Wpf.Sample/Views/SampleWindow.xaml b/Notifications.Wpf.Sample/Views/SampleWindow.xaml index bdd4402..37a6503 100644 --- a/Notifications.Wpf.Sample/Views/SampleWindow.xaml +++ b/Notifications.Wpf.Sample/Views/SampleWindow.xaml @@ -12,10 +12,9 @@ xmlns:helpers="clr-namespace:Notification.Wpf.Sample.Helpers" xmlns:fa5="http://schemas.fontawesome.com/icons/" xmlns:helpers1="clr-namespace:Notification.Wpf.Sample.Helpers;assembly=Notification.Wpf" + xmlns:constants="clr-namespace:Notification.Wpf.Constants;assembly=Notification.Wpf" mc:Ignorable="d" - WindowState="Maximized" - ResizeMode="CanMinimize" - Title="SampleWindow" Height="1200" Width="1920" + Title="SampleWindow" DataContext="{Binding SampleModel, Source={StaticResource Locator}}" d:DataContext="{d:DesignInstance viewModels:SampleWindowViewModel, IsDesignTimeCreatable=True }"> @@ -37,253 +36,255 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - + - + - - - - - - - + + + + + + - + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + - - - - - + + + + + - - - - - - - - + + + + + + + - - + + - - + + - - - - - + + + + - - - + - - - - - - - + + + + + + + - + - - + + - - + - - - + + - - - - - - - - + + + + + + + - - - - - + + + + - - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - + + + - - - - + + + - + - - - + + + - - - - - - -