diff --git a/src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs b/src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs new file mode 100644 index 0000000000..6aaa224b00 --- /dev/null +++ b/src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs @@ -0,0 +1,27 @@ +using Avalonia.Media; + +#nullable enable + +namespace Avalonia +{ + /// + /// Extensions for . + /// + public static class AvaloniaPropertyExtensions + { + /// + /// Checks if values of given property can affect rendering (via ). + /// + /// Property to check. + public static bool CanValueAffectRender(this AvaloniaProperty property) + { + var propertyType = property.PropertyType; + + // Only case that we are sure that property value CAN'T affect render are sealed types that don't implement + // the interface. + var cannotAffectRender = propertyType.IsSealed && !typeof(IAffectsRender).IsAssignableFrom(propertyType); + + return !cannotAffectRender; + } + } +} diff --git a/src/Avalonia.Visuals/Media/Brush.cs b/src/Avalonia.Visuals/Media/Brush.cs index f36cd88537..0d08f92685 100644 --- a/src/Avalonia.Visuals/Media/Brush.cs +++ b/src/Avalonia.Visuals/Media/Brush.cs @@ -69,14 +69,14 @@ namespace Avalonia.Media protected static void AffectsRender(params AvaloniaProperty[] properties) where T : Brush { - void Invalidate(AvaloniaPropertyChangedEventArgs e) + static void Invalidate(AvaloniaPropertyChangedEventArgs e) { (e.Sender as T)?.RaiseInvalidated(EventArgs.Empty); } foreach (var property in properties) { - property.Changed.Subscribe(Invalidate); + property.Changed.Subscribe(e => Invalidate(e)); } } diff --git a/src/Avalonia.Visuals/Media/Pen.cs b/src/Avalonia.Visuals/Media/Pen.cs index b88fae28ff..8ab2b11331 100644 --- a/src/Avalonia.Visuals/Media/Pen.cs +++ b/src/Avalonia.Visuals/Media/Pen.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Collections.Generic; using Avalonia.Media.Immutable; using Avalonia.Utilities; @@ -197,7 +196,15 @@ namespace Avalonia.Media protected static void AffectsRender(params AvaloniaProperty[] properties) where T : Pen { - void Invalidate(AvaloniaPropertyChangedEventArgs e) + static void Invalidate(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is T sender) + { + sender.RaiseInvalidated(EventArgs.Empty); + } + } + + static void InvalidateAndSubscribe(AvaloniaPropertyChangedEventArgs e) { if (e.Sender is T sender) { @@ -223,7 +230,14 @@ namespace Avalonia.Media foreach (var property in properties) { - property.Changed.Subscribe(Invalidate); + if (property.CanValueAffectRender()) + { + property.Changed.Subscribe(e => InvalidateAndSubscribe(e)); + } + else + { + property.Changed.Subscribe(e => Invalidate(e)); + } } } diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index bd2ab6e614..d9032cfa3e 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Specialized; -using System.Linq; using Avalonia.Collections; using Avalonia.Data; using Avalonia.Logging; @@ -336,7 +335,15 @@ namespace Avalonia protected static void AffectsRender(params AvaloniaProperty[] properties) where T : Visual { - void Invalidate(AvaloniaPropertyChangedEventArgs e) + static void Invalidate(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is T sender) + { + sender.InvalidateVisual(); + } + } + + static void InvalidateAndSubscribe(AvaloniaPropertyChangedEventArgs e) { if (e.Sender is T sender) { @@ -347,7 +354,7 @@ namespace Avalonia if (e.NewValue is IAffectsRender newValue) { - WeakEventHandlerManager.Subscribe(newValue, nameof(newValue.Invalidated), sender.AffectsRenderInvalidated); + WeakEventHandlerManager.Subscribe(newValue, nameof(newValue.Invalidated), sender.AffectsRenderInvalidated); } sender.InvalidateVisual(); @@ -356,7 +363,14 @@ namespace Avalonia foreach (var property in properties) { - property.Changed.Subscribe(Invalidate); + if (property.CanValueAffectRender()) + { + property.Changed.Subscribe(e => InvalidateAndSubscribe(e)); + } + else + { + property.Changed.Subscribe(e => Invalidate(e)); + } } }