diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs
index 7d6df716b8..9e9b84537b 100644
--- a/src/Avalonia.Animation/Animatable.cs
+++ b/src/Avalonia.Animation/Animatable.cs
@@ -22,14 +22,10 @@ namespace Avalonia.Animation
///
/// Defines the property.
///
- public static readonly DirectProperty TransitionsProperty =
- AvaloniaProperty.RegisterDirect(
- nameof(Transitions),
- o => o.Transitions,
- (o, v) => o.Transitions = v);
+ public static readonly StyledProperty TransitionsProperty =
+ AvaloniaProperty.Register(nameof(Transitions));
private bool _transitionsEnabled = true;
- private Transitions? _transitions;
private Dictionary? _transitionState;
///
@@ -44,36 +40,10 @@ namespace Avalonia.Animation
///
/// Gets or sets the property transitions for the control.
///
- public Transitions Transitions
+ public Transitions? Transitions
{
- get
- {
- if (_transitions is null)
- {
- _transitions = new Transitions();
- _transitions.CollectionChanged += TransitionsCollectionChanged;
- }
-
- return _transitions;
- }
- set
- {
- // TODO: This is a hack, Setter should not replace transitions, but should add/remove.
- if (value is null)
- {
- return;
- }
-
- if (_transitions is object)
- {
- RemoveTransitions(_transitions);
- _transitions.CollectionChanged -= TransitionsCollectionChanged;
- }
-
- SetAndRaise(TransitionsProperty, ref _transitions, value);
- _transitions.CollectionChanged += TransitionsCollectionChanged;
- AddTransitions(_transitions);
- }
+ get => GetValue(TransitionsProperty);
+ set => SetValue(TransitionsProperty, value);
}
///
@@ -89,9 +59,9 @@ namespace Avalonia.Animation
{
_transitionsEnabled = true;
- if (_transitions is object)
+ if (Transitions is object)
{
- AddTransitions(_transitions);
+ AddTransitions(Transitions);
}
}
}
@@ -109,21 +79,39 @@ namespace Avalonia.Animation
{
_transitionsEnabled = false;
- if (_transitions is object)
+ if (Transitions is object)
{
- RemoveTransitions(_transitions);
+ RemoveTransitions(Transitions);
}
}
}
protected sealed override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change)
{
- if (_transitionsEnabled &&
- _transitions is object &&
- _transitionState is object &&
- change.Priority > BindingPriority.Animation)
+ if (change.Property == TransitionsProperty && change.IsEffectiveValueChange)
+ {
+ var oldTransitions = change.OldValue.GetValueOrDefault();
+ var newTransitions = change.NewValue.GetValueOrDefault();
+
+ if (oldTransitions is object)
+ {
+ oldTransitions.CollectionChanged -= TransitionsCollectionChanged;
+ RemoveTransitions(oldTransitions);
+ }
+
+ if (newTransitions is object)
+ {
+ newTransitions.CollectionChanged += TransitionsCollectionChanged;
+ AddTransitions(newTransitions);
+ }
+ }
+ else if (_transitionsEnabled &&
+ Transitions is object &&
+ _transitionState is object &&
+ !change.Property.IsDirect &&
+ change.Priority > BindingPriority.Animation)
{
- foreach (var transition in _transitions)
+ foreach (var transition in Transitions)
{
if (transition.Property == change.Property)
{
diff --git a/src/Avalonia.Animation/TransitionInstance.cs b/src/Avalonia.Animation/TransitionInstance.cs
index efbbed51b5..ad2001d621 100644
--- a/src/Avalonia.Animation/TransitionInstance.cs
+++ b/src/Avalonia.Animation/TransitionInstance.cs
@@ -19,6 +19,8 @@ namespace Avalonia.Animation
public TransitionInstance(IClock clock, TimeSpan Duration)
{
+ clock = clock ?? throw new ArgumentNullException(nameof(clock));
+
_duration = Duration;
_baseClock = clock;
}
diff --git a/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs b/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs
index e1169650a9..b5c61883e7 100644
--- a/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs
+++ b/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs
@@ -1,6 +1,7 @@
using System;
using Avalonia.Controls;
using Avalonia.Data;
+using Avalonia.Layout;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Moq;
@@ -16,7 +17,7 @@ namespace Avalonia.Animation.UnitTests
var target = CreateTarget();
var control = new Control
{
- Transitions = { target.Object },
+ Transitions = new Transitions { target.Object },
};
control.Opacity = 0.5;
@@ -37,7 +38,7 @@ namespace Avalonia.Animation.UnitTests
var target = CreateTarget();
var control = new Control
{
- Transitions = { target.Object },
+ Transitions = new Transitions { target.Object },
};
var root = new TestRoot
@@ -213,30 +214,126 @@ namespace Avalonia.Animation.UnitTests
sub.Verify(x => x.Dispose());
}
- private static Mock CreateTarget()
+ [Fact]
+ public void Animation_Is_Cancelled_When_New_Style_Activates()
{
- var target = new Mock();
- var sub = new Mock();
+ using (UnitTestApplication.Start(TestServices.RealStyler))
+ {
+ var target = CreateTarget();
+ var control = CreateStyledControl(target.Object);
+ var sub = new Mock();
- target.Setup(x => x.Property).Returns(Visual.OpacityProperty);
- target.Setup(x => x.Apply(
- It.IsAny(),
- It.IsAny(),
- It.IsAny