diff --git a/.gitignore b/.gitignore
index bf2e5be0a..889428054 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/.vs
+/packages
/HandyControl/bin/Debug
/HandyControl/obj/Debug
/HandyControl/bin/Release
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 68e6fdd2c..f69316d0e 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,17 @@
+2018.09.04 Version 1.2.0
+* new controls
+ - add Growl
+ - add AnimationPath
+ - add TransitioningContentControl
+
+* new style
+ - add ProgressBar
+ - add TreeView
+
+* other
+- update HandyControlDemo UI
+- the ScrollViewer will auto hidden
+
2018.08.31 Version 1.1.2
* new controls
- add CompareSlider
diff --git a/HandyControl/Controls/AnimationPath.cs b/HandyControl/Controls/AnimationPath.cs
new file mode 100644
index 000000000..ce23dbbc0
--- /dev/null
+++ b/HandyControl/Controls/AnimationPath.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+namespace HandyControl.Controls
+{
+ public class AnimationPath : Shape
+ {
+ private bool _isLoaded;
+
+ ///
+ /// 故事版
+ ///
+ private Storyboard _storyboard;
+
+ ///
+ /// 路径
+ ///
+ public static readonly DependencyProperty DataProperty = DependencyProperty.Register(nameof(Data),
+ typeof(Geometry), typeof(AnimationPath), new FrameworkPropertyMetadata(null,
+ OnPropertiesChanged));
+
+ private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is AnimationPath path)
+ {
+ path.UpdatePath();
+ }
+ }
+
+ ///
+ /// 路径
+ ///
+ public Geometry Data
+ {
+ get => (Geometry)GetValue(DataProperty);
+ set => SetValue(DataProperty, value);
+ }
+
+ protected override Geometry DefiningGeometry => Data ?? Geometry.Empty;
+
+ ///
+ /// 路径长度
+ ///
+ public static readonly DependencyProperty PathLengthProperty = DependencyProperty.Register(
+ "PathLength", typeof(double), typeof(AnimationPath), new FrameworkPropertyMetadata(default(double),
+ OnPropertiesChanged));
+
+ ///
+ /// 路径长度
+ ///
+ public double PathLength
+ {
+ get => (double)GetValue(PathLengthProperty);
+ set => SetValue(PathLengthProperty, value);
+ }
+
+ ///
+ /// 动画间隔时间
+ ///
+ public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
+ "Duration", typeof(Duration), typeof(AnimationPath), new FrameworkPropertyMetadata(new Duration(TimeSpan.FromSeconds(2)),
+ OnPropertiesChanged));
+
+ ///
+ /// 动画间隔时间
+ ///
+ public Duration Duration
+ {
+ get => (Duration)GetValue(DurationProperty);
+ set => SetValue(DurationProperty, value);
+ }
+
+ public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register(
+ "IsPlaying", typeof(bool), typeof(AnimationPath), new FrameworkPropertyMetadata(true, (o, args) =>
+ {
+ var ctl = (AnimationPath)o;
+ var v = (bool)args.NewValue;
+ if (v)
+ {
+ ctl.UpdatePath();
+ }
+ else
+ {
+ ctl._storyboard?.Pause();
+ }
+ }));
+
+ ///
+ /// 是否正在播放动画
+ ///
+ public bool IsPlaying
+ {
+ get => (bool)GetValue(IsPlayingProperty);
+ set => SetValue(IsPlayingProperty, value);
+ }
+
+ public static readonly DependencyProperty RepeatBehaviorProperty = DependencyProperty.Register(
+ "RepeatBehavior", typeof(RepeatBehavior), typeof(AnimationPath), new PropertyMetadata(RepeatBehavior.Forever));
+
+ ///
+ /// 动画重复行为
+ ///
+ public RepeatBehavior RepeatBehavior
+ {
+ get => (RepeatBehavior)GetValue(RepeatBehaviorProperty);
+ set => SetValue(RepeatBehaviorProperty, value);
+ }
+
+ static AnimationPath()
+ {
+ StretchProperty.AddOwner(typeof(AnimationPath), new FrameworkPropertyMetadata(Stretch.Uniform,
+ OnPropertiesChanged));
+
+ StrokeThicknessProperty.AddOwner(typeof(AnimationPath), new FrameworkPropertyMetadata(1.0,
+ OnPropertiesChanged));
+ }
+
+ public AnimationPath()
+ {
+ Loaded += (s, e) =>
+ {
+ if (_isLoaded) return;
+ UpdatePath();
+ _isLoaded = true;
+ };
+ }
+
+ ///
+ /// 动画完成事件
+ ///
+ public static readonly RoutedEvent CompletedEvent =
+ EventManager.RegisterRoutedEvent("Completed", RoutingStrategy.Bubble,
+ typeof(EventHandler), typeof(AnimationPath));
+
+ ///
+ /// 动画完成事件
+ ///
+ public event EventHandler Completed
+ {
+ add => AddHandler(CompletedEvent, value);
+ remove => RemoveHandler(CompletedEvent, value);
+ }
+
+ private void UpdatePath()
+ {
+ if (!Duration.HasTimeSpan || !IsPlaying) return;
+ StrokeDashOffset = PathLength;
+ StrokeDashArray = new DoubleCollection(new List
+ {
+ PathLength,
+ PathLength
+ });
+
+ //定义动画
+ _storyboard = new Storyboard
+ {
+ RepeatBehavior = RepeatBehavior
+ };
+ _storyboard.Completed += (s, e) => RaiseEvent(new RoutedEventArgs(CompletedEvent));
+
+ var frames = new DoubleAnimationUsingKeyFrames();
+ //开始位置
+ var frame0 = new LinearDoubleKeyFrame
+ {
+ Value = PathLength,
+ KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
+ };
+ //结束位置
+ var frame1 = new LinearDoubleKeyFrame
+ {
+ Value = -PathLength,
+ KeyTime = KeyTime.FromTimeSpan(Duration.TimeSpan)
+ };
+ frames.KeyFrames.Add(frame0);
+ frames.KeyFrames.Add(frame1);
+
+ Storyboard.SetTarget(frames, this);
+ Storyboard.SetTargetProperty(frames, new PropertyPath(StrokeDashOffsetProperty));
+ _storyboard.Children.Add(frames);
+
+ _storyboard.Begin();
+ }
+ }
+}
\ No newline at end of file
diff --git a/HandyControl/Controls/Attach/BackgroundSwitchElement.cs b/HandyControl/Controls/Attach/BackgroundSwitchElement.cs
new file mode 100644
index 000000000..1711f7d88
--- /dev/null
+++ b/HandyControl/Controls/Attach/BackgroundSwitchElement.cs
@@ -0,0 +1,35 @@
+using System.Windows;
+using System.Windows.Media;
+
+// ReSharper disable once CheckNamespace
+namespace HandyControl.Controls
+{
+ public class BackgroundSwitchElement : DependencyObject
+ {
+ public static readonly DependencyProperty MouseHoverBackgroundProperty = DependencyProperty.RegisterAttached(
+ "MouseHoverBackground", typeof(Brush), typeof(BackgroundSwitchElement), new PropertyMetadata(Brushes.Transparent));
+
+ public static void SetMouseHoverBackground(DependencyObject element, Brush value)
+ {
+ element.SetValue(MouseHoverBackgroundProperty, value);
+ }
+
+ public static Brush GetMouseHoverBackground(DependencyObject element)
+ {
+ return (Brush)element.GetValue(MouseHoverBackgroundProperty);
+ }
+
+ public static readonly DependencyProperty MouseDownBackgroundProperty = DependencyProperty.RegisterAttached(
+ "MouseDownBackground", typeof(Brush), typeof(BackgroundSwitchElement), new PropertyMetadata(Brushes.Transparent));
+
+ public static void SetMouseDownBackground(DependencyObject element, Brush value)
+ {
+ element.SetValue(MouseDownBackgroundProperty, value);
+ }
+
+ public static Brush GetMouseDownBackground(DependencyObject element)
+ {
+ return (Brush)element.GetValue(MouseDownBackgroundProperty);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HandyControl/Controls/Attach/BorderElement.cs b/HandyControl/Controls/Attach/BorderElement.cs
new file mode 100644
index 000000000..77b24384e
--- /dev/null
+++ b/HandyControl/Controls/Attach/BorderElement.cs
@@ -0,0 +1,21 @@
+using System.Windows;
+
+// ReSharper disable once CheckNamespace
+namespace HandyControl.Controls
+{
+ public class BorderElement : DependencyObject
+ {
+ public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached(
+ "CornerRadius", typeof(CornerRadius), typeof(BorderElement), new PropertyMetadata(default(CornerRadius)));
+
+ public static void SetCornerRadius(DependencyObject element, CornerRadius value)
+ {
+ element.SetValue(CornerRadiusProperty, value);
+ }
+
+ public static CornerRadius GetCornerRadius(DependencyObject element)
+ {
+ return (CornerRadius) element.GetValue(CornerRadiusProperty);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HandyControl/Controls/ColorPicker.xaml b/HandyControl/Controls/ColorPicker.xaml
index 22a683d51..2e0005c6e 100644
--- a/HandyControl/Controls/ColorPicker.xaml
+++ b/HandyControl/Controls/ColorPicker.xaml
@@ -75,24 +75,6 @@
-