diff --git a/src/Avalonia.Visuals/Media/DashStyle.cs b/src/Avalonia.Visuals/Media/DashStyle.cs
index 1e813edc13..acba2d3615 100644
--- a/src/Avalonia.Visuals/Media/DashStyle.cs
+++ b/src/Avalonia.Visuals/Media/DashStyle.cs
@@ -1,11 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Avalonia.Animation;
+using Avalonia.Collections;
+using Avalonia.Media.Immutable;
+
+#nullable enable
+
namespace Avalonia.Media
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Avalonia.Animation;
- using Avalonia.Media.Immutable;
-
///
/// Represents the sequence of dashes and gaps that will be applied by a .
///
@@ -14,8 +17,8 @@ namespace Avalonia.Media
///
/// Defines the property.
///
- public static readonly StyledProperty> DashesProperty =
- AvaloniaProperty.Register>(nameof(Dashes));
+ public static readonly StyledProperty> DashesProperty =
+ AvaloniaProperty.Register>(nameof(Dashes));
///
/// Defines the property.
@@ -23,10 +26,10 @@ namespace Avalonia.Media
public static readonly StyledProperty OffsetProperty =
AvaloniaProperty.Register(nameof(Offset));
- private static ImmutableDashStyle s_dash;
- private static ImmutableDashStyle s_dot;
- private static ImmutableDashStyle s_dashDot;
- private static ImmutableDashStyle s_dashDotDot;
+ private static ImmutableDashStyle? s_dash;
+ private static ImmutableDashStyle? s_dot;
+ private static ImmutableDashStyle? s_dashDot;
+ private static ImmutableDashStyle? s_dashDotDot;
///
/// Initializes a new instance of the class.
@@ -41,9 +44,9 @@ namespace Avalonia.Media
///
/// The dashes collection.
/// The dash sequence offset.
- public DashStyle(IEnumerable dashes, double offset)
+ public DashStyle(IEnumerable? dashes, double offset)
{
- Dashes = (IReadOnlyList)dashes?.ToList() ?? Array.Empty();
+ Dashes = (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty());
Offset = offset;
}
@@ -61,31 +64,27 @@ namespace Avalonia.Media
///
/// Represents a dashed .
///
- public static IDashStyle Dash =>
- s_dash ?? (s_dash = new ImmutableDashStyle(new double[] { 2, 2 }, 1));
+ public static IDashStyle Dash => s_dash ??= new ImmutableDashStyle(new double[] { 2, 2 }, 1);
///
/// Represents a dotted .
///
- public static IDashStyle Dot =>
- s_dot ?? (s_dot = new ImmutableDashStyle(new double[] { 0, 2 }, 0));
+ public static IDashStyle Dot => s_dot ??= new ImmutableDashStyle(new double[] { 0, 2 }, 0);
///
/// Represents a dashed dotted .
///
- public static IDashStyle DashDot =>
- s_dashDot ?? (s_dashDot = new ImmutableDashStyle(new double[] { 2, 2, 0, 2 }, 1));
+ public static IDashStyle DashDot => s_dashDot ??= new ImmutableDashStyle(new double[] { 2, 2, 0, 2 }, 1);
///
/// Represents a dashed double dotted .
///
- public static IDashStyle DashDotDot =>
- s_dashDotDot ?? (s_dashDotDot = new ImmutableDashStyle(new double[] { 2, 2, 0, 2, 0, 2 }, 1));
+ public static IDashStyle DashDotDot => s_dashDotDot ??= new ImmutableDashStyle(new double[] { 2, 2, 0, 2, 0, 2 }, 1);
///
/// Gets or sets the length of alternating dashes and gaps.
///
- public IReadOnlyList Dashes
+ public AvaloniaList Dashes
{
get => GetValue(DashesProperty);
set => SetValue(DashesProperty, value);
@@ -100,15 +99,43 @@ namespace Avalonia.Media
set => SetValue(OffsetProperty, value);
}
+ IReadOnlyList IDashStyle.Dashes => Dashes;
+
///
/// Raised when the dash style changes.
///
- public event EventHandler Invalidated;
+ public event EventHandler? Invalidated;
///
/// Returns an immutable clone of the .
///
///
public ImmutableDashStyle ToImmutable() => new ImmutableDashStyle(Dashes, Offset);
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == DashesProperty)
+ {
+ var oldValue = change.OldValue.GetValueOrDefault>();
+ var newValue = change.NewValue.GetValueOrDefault>();
+
+ if (oldValue is object)
+ {
+ oldValue.CollectionChanged -= DashesChanged;
+ }
+
+ if (newValue is object)
+ {
+ newValue.CollectionChanged += DashesChanged;
+ }
+ }
+ }
+
+ private void DashesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ Invalidated?.Invoke(this, e);
+ }
}
}
diff --git a/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs
index 418ac7576b..c2a1a5f9e4 100644
--- a/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs
+++ b/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs
@@ -1,4 +1,5 @@
-using Avalonia.Media;
+using Avalonia.Collections;
+using Avalonia.Media;
using Avalonia.Media.Immutable;
using Xunit;
@@ -39,7 +40,20 @@ namespace Avalonia.Visuals.UnitTests.Media
var raised = false;
target.Invalidated += (s, e) => raised = true;
- dashes.Dashes = new[] { 0.1, 0.2 };
+ dashes.Dashes = new AvaloniaList { 0.1, 0.2 };
+
+ Assert.True(raised);
+ }
+
+ [Fact]
+ public void Adding_DashStyle_Dashes_Raises_Invalidated()
+ {
+ var dashes = new DashStyle();
+ var target = new Pen { DashStyle = dashes };
+ var raised = false;
+
+ target.Invalidated += (s, e) => raised = true;
+ dashes.Dashes.Add(0.3);
Assert.True(raised);
}