diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs index 3a3d00b94a..2c321b8b28 100644 --- a/src/Avalonia.Animation/Animatable.cs +++ b/src/Avalonia.Animation/Animatable.cs @@ -45,16 +45,17 @@ namespace Avalonia.Animation { get { - if (_transitions == null) + if (_transitions is null) _transitions = new Transitions(); - if (_previousTransitions == null) + if (_previousTransitions is null) _previousTransitions = new Dictionary(); return _transitions; } set { + SetAndRaise(TransitionsProperty, ref _transitions, value); } } @@ -66,18 +67,20 @@ namespace Avalonia.Animation /// The event args. protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) { - if (e.Priority != BindingPriority.Animation && Transitions != null && _previousTransitions != null) - { - var match = Transitions.FirstOrDefault(x => x.Property == e.Property); + if (_transitions is null || _previousTransitions is null || e.Priority == BindingPriority.Animation) return; - if (match != null) + // PERF-SENSITIVE: Called on every property change. Don't use LINQ here (too many allocations). + foreach (var transition in Transitions) + { + if (transition.Property == e.Property) { if (_previousTransitions.TryGetValue(e.Property, out var dispose)) dispose.Dispose(); - var instance = match.Apply(this, Clock ?? Avalonia.Animation.Clock.GlobalClock, e.OldValue, e.NewValue); + var instance = transition.Apply(this, Clock ?? Avalonia.Animation.Clock.GlobalClock, e.OldValue, e.NewValue); _previousTransitions[e.Property] = instance; + return; } } }