From 83fc434e7d8da4758c7c5881a475d99fa847a966 Mon Sep 17 00:00:00 2001
From: NaBian <836904362@qq.com>
Date: Mon, 8 Sep 2025 23:20:47 +0800
Subject: [PATCH] enhance: Growl demo.
---
src/Shared/HandyControlDemo_Shared/App.xaml | 5 +-
.../UserControl/Controls/GrowlDemo.xaml | 90 ++++++++++---
.../ViewModel/Controls/GrowlDemoViewModel.cs | 23 +++-
.../Controls/Growl/Growl.cs | 120 +++++++++++-------
.../Data/Info/GrowlInfo.cs | 1 +
5 files changed, 168 insertions(+), 71 deletions(-)
diff --git a/src/Shared/HandyControlDemo_Shared/App.xaml b/src/Shared/HandyControlDemo_Shared/App.xaml
index da21212a..41ed87ee 100644
--- a/src/Shared/HandyControlDemo_Shared/App.xaml
+++ b/src/Shared/HandyControlDemo_Shared/App.xaml
@@ -2,12 +2,12 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:HandyControlDemo.ViewModel"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:d1P1="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="clr-namespace:HandyControlDemo.Data"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
- d1P1:Ignorable="d"
+ d1P1:Ignorable="d"
StartupUri="MainWindow.xaml">
@@ -30,6 +30,7 @@
+
diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/GrowlDemo.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/GrowlDemo.xaml
index 55213a12..4caecda5 100644
--- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/GrowlDemo.xaml
+++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/GrowlDemo.xaml
@@ -7,30 +7,82 @@
DataContext="{Binding GrowlDemo,Source={StaticResource Locator}}"
Background="{DynamicResource RegionBrush}">
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
diff --git a/src/Shared/HandyControlDemo_Shared/ViewModel/Controls/GrowlDemoViewModel.cs b/src/Shared/HandyControlDemo_Shared/ViewModel/Controls/GrowlDemoViewModel.cs
index 6d31554f..a24dd0be 100644
--- a/src/Shared/HandyControlDemo_Shared/ViewModel/Controls/GrowlDemoViewModel.cs
+++ b/src/Shared/HandyControlDemo_Shared/ViewModel/Controls/GrowlDemoViewModel.cs
@@ -1,4 +1,5 @@
using System.Windows;
+using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using HandyControl.Controls;
using HandyControl.Data;
@@ -6,10 +7,12 @@ using HandyControlDemo.Window;
namespace HandyControlDemo.ViewModel;
-public class GrowlDemoViewModel
+public class GrowlDemoViewModel : ViewModelBase
{
private readonly string _token;
+ private TransitionMode _transitionMode;
+
public GrowlDemoViewModel()
{
@@ -20,6 +23,24 @@ public class GrowlDemoViewModel
_token = token;
}
+ public TransitionMode TransitionMode
+ {
+ get => _transitionMode;
+#if NET40
+ set
+ {
+ Set(nameof(TransitionMode), ref _transitionMode, value);
+ Growl.SetTransitionMode(Application.Current.MainWindow, value);
+ }
+#else
+ set
+ {
+ Set(ref _transitionMode, value);
+ Growl.SetTransitionMode(Application.Current.MainWindow, value);
+ }
+#endif
+ }
+
#region Window
public RelayCommand InfoCmd => new(() => Growl.Info(Properties.Langs.Lang.GrowlInfo, _token));
diff --git a/src/Shared/HandyControl_Shared/Controls/Growl/Growl.cs b/src/Shared/HandyControl_Shared/Controls/Growl/Growl.cs
index 68bb4d36..17401d2d 100644
--- a/src/Shared/HandyControl_Shared/Controls/Growl/Growl.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Growl/Growl.cs
@@ -47,11 +47,13 @@ public class Growl : Control
"ShowMode", typeof(GrowlShowMode), typeof(Growl),
new FrameworkPropertyMetadata(default(GrowlShowMode), FrameworkPropertyMetadataOptions.Inherits));
- public static readonly DependencyProperty TransitionModeProperty = DependencyProperty.Register(
- nameof(TransitionMode), typeof(TransitionMode), typeof(Growl), new PropertyMetadata(default(TransitionMode)));
+ public static readonly DependencyProperty TransitionModeProperty = DependencyProperty.RegisterAttached(
+ "TransitionMode", typeof(TransitionMode), typeof(Growl),
+ new FrameworkPropertyMetadata(default(TransitionMode), FrameworkPropertyMetadataOptions.Inherits));
- public static readonly DependencyProperty TransitionStoryboardProperty = DependencyProperty.Register(
- nameof(TransitionStoryboard), typeof(Storyboard), typeof(Growl), new PropertyMetadata(default(Storyboard)));
+ public static readonly DependencyProperty TransitionStoryboardProperty = DependencyProperty.RegisterAttached(
+ "TransitionStoryboard", typeof(Storyboard), typeof(Growl),
+ new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
public static readonly DependencyProperty ShowDateTimeProperty = DependencyProperty.Register(
nameof(ShowDateTime), typeof(bool), typeof(Growl), new PropertyMetadata(ValueBoxes.TrueBox));
@@ -105,18 +107,6 @@ public class Growl : Control
///
public static Panel GrowlPanel { get; set; }
- public TransitionMode TransitionMode
- {
- get => (TransitionMode) GetValue(TransitionModeProperty);
- set => SetValue(TransitionModeProperty, value);
- }
-
- public Storyboard TransitionStoryboard
- {
- get => (Storyboard) GetValue(TransitionStoryboardProperty);
- set => SetValue(TransitionStoryboardProperty, value);
- }
-
public InfoType Type
{
get => (InfoType) GetValue(TypeProperty);
@@ -231,6 +221,18 @@ public class Growl : Control
public static GrowlShowMode GetShowMode(DependencyObject element) =>
(GrowlShowMode) element.GetValue(ShowModeProperty);
+ public static void SetTransitionMode(DependencyObject element, TransitionMode value)
+ => element.SetValue(TransitionModeProperty, value);
+
+ public static TransitionMode GetTransitionMode(DependencyObject element)
+ => (TransitionMode) element.GetValue(TransitionModeProperty);
+
+ public static void SetTransitionStoryboard(DependencyObject element, Storyboard value)
+ => element.SetValue(TransitionStoryboardProperty, value);
+
+ public static Storyboard GetTransitionStoryboard(DependencyObject element)
+ => (Storyboard) element.GetValue(TransitionStoryboardProperty);
+
public static void SetGrowlParent(DependencyObject element, bool value) =>
element.SetValue(GrowlParentProperty, ValueBoxes.BooleanBox(value));
@@ -371,7 +373,6 @@ public class Growl : Control
CancelStr = growlInfo.CancelStr,
Type = growlInfo.Type,
_waitTime = Math.Max(growlInfo.WaitTime, MinWaitTime),
- FlowDirection = growlInfo.FlowDirection
};
ShowInternal(GrowlWindow.GrowlPanel, ctl);
@@ -422,6 +423,10 @@ public class Growl : Control
// GrowlPanel is null, we create it automatically
GrowlPanel ??= CreateDefaultPanel();
ShowInternal(GrowlPanel, ctl);
+
+ var transitionMode = GetTransitionMode(ctl);
+ GrowlPanel.VerticalAlignment = GetPanelVerticalAlignment(transitionMode);
+ GrowlPanel.HorizontalAlignment = GetPanelHorizontalAlignment(transitionMode);
}
}
#if NET40
@@ -435,40 +440,33 @@ public class Growl : Control
FrameworkElement element = WindowHelper.GetActiveWindow();
var decorator = VisualHelper.GetChild(element);
- if (decorator != null)
+ var layer = decorator?.AdornerLayer;
+ if (layer == null)
{
- var layer = decorator.AdornerLayer;
- if (layer != null)
- {
- var panel = new StackPanel
- {
- VerticalAlignment = VerticalAlignment.Top
- };
-
- InitGrowlPanel(panel);
- SetIsCreatedAutomatically(panel, true);
-
- var scrollViewer = new ScrollViewer
- {
- HorizontalAlignment = HorizontalAlignment.Right,
- VerticalScrollBarVisibility = ScrollBarVisibility.Hidden,
- IsInertiaEnabled = true,
- IsPenetrating = true,
- Content = panel
- };
-
- var container = new AdornerContainer(layer)
- {
- Child = scrollViewer
- };
-
- layer.Add(container);
-
- return panel;
- }
+ return null;
}
- return null;
+ var panel = new SimpleStackPanel();
+
+ InitGrowlPanel(panel);
+ SetIsCreatedAutomatically(panel, true);
+
+ var scrollViewer = new ScrollViewer
+ {
+ VerticalScrollBarVisibility = ScrollBarVisibility.Hidden,
+ IsInertiaEnabled = true,
+ IsPenetrating = true,
+ Content = panel
+ };
+
+ var container = new AdornerContainer(layer)
+ {
+ Child = scrollViewer
+ };
+
+ layer.Add(container);
+
+ return panel;
}
private static void RemoveDefaultPanel(Panel panel)
@@ -918,7 +916,7 @@ public class Growl : Control
private void StartTransition(bool isClose, Action completed = null)
{
- var actualStoryboard = TransitionStoryboard ?? CreateStoryboard(isClose, TransitionMode);
+ var actualStoryboard = GetTransitionStoryboard(this) ?? CreateStoryboard(isClose, GetTransitionMode(this));
if (actualStoryboard is null)
{
return;
@@ -1064,4 +1062,28 @@ public class Growl : Control
_ => null
};
}
+
+ private static VerticalAlignment GetPanelVerticalAlignment(TransitionMode transitionMode)
+ {
+ return transitionMode switch
+ {
+ TransitionMode.Right2Left or TransitionMode.Right2LeftWithFade or TransitionMode.Left2Right
+ or TransitionMode.Left2RightWithFade => VerticalAlignment.Top,
+ TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade => VerticalAlignment.Bottom,
+ TransitionMode.Top2Bottom or TransitionMode.Top2BottomWithFade => VerticalAlignment.Top,
+ _ => VerticalAlignment.Stretch
+ };
+ }
+
+ private static HorizontalAlignment GetPanelHorizontalAlignment(TransitionMode transitionMode)
+ {
+ return transitionMode switch
+ {
+ TransitionMode.Right2Left or TransitionMode.Right2LeftWithFade => HorizontalAlignment.Right,
+ TransitionMode.Left2Right or TransitionMode.Left2RightWithFade => HorizontalAlignment.Left,
+ TransitionMode.Bottom2Top or TransitionMode.Bottom2TopWithFade or TransitionMode.Top2Bottom
+ or TransitionMode.Top2BottomWithFade => HorizontalAlignment.Center,
+ _ => HorizontalAlignment.Stretch
+ };
+ }
}
diff --git a/src/Shared/HandyControl_Shared/Data/Info/GrowlInfo.cs b/src/Shared/HandyControl_Shared/Data/Info/GrowlInfo.cs
index 44464b99..498626ef 100644
--- a/src/Shared/HandyControl_Shared/Data/Info/GrowlInfo.cs
+++ b/src/Shared/HandyControl_Shared/Data/Info/GrowlInfo.cs
@@ -37,6 +37,7 @@ public class GrowlInfo
public string Token { get; set; }
+ [Obsolete("use TransitionMode instead")]
public FlowDirection FlowDirection { get; set; }
public Dispatcher Dispatcher { get; set; }