diff --git a/src/Avalonia.Base/Animation/Transition.cs b/src/Avalonia.Base/Animation/Transition.cs
index 519ed52578..2ad92c9183 100644
--- a/src/Avalonia.Base/Animation/Transition.cs
+++ b/src/Avalonia.Base/Animation/Transition.cs
@@ -1,53 +1,22 @@
using System;
-using System.Diagnostics.CodeAnalysis;
-using Avalonia.Animation.Easings;
namespace Avalonia.Animation
{
///
/// Defines how a property should be animated using a transition.
///
- public abstract class Transition : AvaloniaObject, ITransition
+ public abstract class Transition : TransitionBase
{
- private AvaloniaProperty? _prop;
-
- ///
- /// Gets or sets the duration of the transition.
- ///
- public TimeSpan Duration { get; set; }
-
- ///
- /// Gets or sets delay before starting the transition.
- ///
- public TimeSpan Delay { get; set; } = TimeSpan.Zero;
-
- ///
- /// Gets the easing class to be used.
- ///
- public Easing Easing { get; set; } = new LinearEasing();
-
- ///
- [DisallowNull]
- public AvaloniaProperty? Property
+ static Transition()
{
- get
- {
- return _prop;
- }
- set
- {
- if (!(value.PropertyType.IsAssignableFrom(typeof(T))))
- throw new InvalidCastException
- ($"Invalid property type \"{typeof(T).Name}\" for this transition: {GetType().Name}.");
-
- _prop = value;
- }
+ PropertyProperty.Changed.AddClassHandler>((x, e) => x.OnPropertyPropertyChanged(e));
}
- AvaloniaProperty ITransition.Property
+ private void OnPropertyPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
- get => Property ?? throw new InvalidOperationException("Transition has no property specified.");
- set => Property = value;
+ if ((e.NewValue is AvaloniaProperty newValue) && !newValue.PropertyType.IsAssignableFrom(typeof(T)))
+ throw new InvalidCastException
+ ($"Invalid property type \"{typeof(T).Name}\" for this transition: {GetType().Name}.");
}
///
@@ -55,11 +24,7 @@ namespace Avalonia.Animation
///
internal abstract IObservable DoTransition(IObservable progress, T oldValue, T newValue);
- ///
- IDisposable ITransition.Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
- => Apply(control, clock, oldValue, newValue);
-
- internal virtual IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
+ internal override IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
{
if (Property is null)
throw new InvalidOperationException("Transition has no property specified.");
diff --git a/src/Avalonia.Base/Animation/TransitionBase.cs b/src/Avalonia.Base/Animation/TransitionBase.cs
new file mode 100644
index 0000000000..8cc06ce7ed
--- /dev/null
+++ b/src/Avalonia.Base/Animation/TransitionBase.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Avalonia.Animation.Easings;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Defines how a property should be animated using a transition.
+ ///
+ public abstract class TransitionBase : AvaloniaObject, ITransition
+ {
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty DurationProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(Duration),
+ o => o._duration,
+ (o, v) => o._duration = v);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty DelayProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(Delay),
+ o => o._delay,
+ (o, v) => o._delay = v);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty EasingProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(Easing),
+ o => o._easing,
+ (o, v) => o._easing = v);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty PropertyProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(Property),
+ o => o._prop,
+ (o, v) => o._prop = v);
+
+ private TimeSpan _duration;
+ private TimeSpan _delay = TimeSpan.Zero;
+ private Easing _easing = new LinearEasing();
+ private AvaloniaProperty? _prop;
+
+ ///
+ /// Gets or sets the duration of the transition.
+ ///
+ public TimeSpan Duration
+ {
+ get { return _duration; }
+ set { SetAndRaise(DurationProperty, ref _duration, value); }
+ }
+
+ ///
+ /// Gets or sets delay before starting the transition.
+ ///
+ public TimeSpan Delay
+ {
+ get { return _delay; }
+ set { SetAndRaise(DelayProperty, ref _delay, value); }
+ }
+
+ ///
+ /// Gets the easing class to be used.
+ ///
+ public Easing Easing
+ {
+ get { return _easing; }
+ set { SetAndRaise(EasingProperty, ref _easing, value); }
+ }
+
+ ///
+ [DisallowNull]
+ public AvaloniaProperty? Property
+ {
+ get { return _prop; }
+ set { SetAndRaise(PropertyProperty, ref _prop, value); }
+ }
+
+ AvaloniaProperty ITransition.Property
+ {
+ get => Property ?? throw new InvalidOperationException("Transition has no property specified.");
+ set => Property = value;
+ }
+
+ ///
+ IDisposable ITransition.Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
+ => Apply(control, clock, oldValue, newValue);
+
+ internal abstract IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue);
+ }
+}