|
|
@@ -14,6 +14,8 @@ namespace Avalonia.Controls
|
|
|
/// </remarks>
|
|
|
public class Classes : AvaloniaList<string>, IPseudoClasses
|
|
|
{
|
|
|
+ private List<IClassesChangedListener>? _listeners;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Initializes a new instance of the <see cref="Classes"/> class.
|
|
|
/// </summary>
|
|
|
@@ -39,6 +41,11 @@ namespace Avalonia.Controls
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Gets the number of listeners subscribed to this collection for unit testing purposes.
|
|
|
+ /// </summary>
|
|
|
+ internal int ListenerCount => _listeners?.Count ?? 0;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Parses a classes string.
|
|
|
/// </summary>
|
|
|
@@ -62,6 +69,7 @@ namespace Avalonia.Controls
|
|
|
if (!Contains(name))
|
|
|
{
|
|
|
base.Add(name);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -89,6 +97,7 @@ namespace Avalonia.Controls
|
|
|
}
|
|
|
|
|
|
base.AddRange(c);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -103,6 +112,8 @@ namespace Avalonia.Controls
|
|
|
RemoveAt(i);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -122,6 +133,7 @@ namespace Avalonia.Controls
|
|
|
if (!Contains(name))
|
|
|
{
|
|
|
base.Insert(index, name);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -154,6 +166,7 @@ namespace Avalonia.Controls
|
|
|
if (toInsert != null)
|
|
|
{
|
|
|
base.InsertRange(index, toInsert);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -169,7 +182,14 @@ namespace Avalonia.Controls
|
|
|
public override bool Remove(string name)
|
|
|
{
|
|
|
ThrowIfPseudoclass(name, "removed");
|
|
|
- return base.Remove(name);
|
|
|
+
|
|
|
+ if (base.Remove(name))
|
|
|
+ {
|
|
|
+ NotifyChanged();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -197,6 +217,7 @@ namespace Avalonia.Controls
|
|
|
if (toRemove != null)
|
|
|
{
|
|
|
base.RemoveAll(toRemove);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -214,6 +235,7 @@ namespace Avalonia.Controls
|
|
|
var name = this[index];
|
|
|
ThrowIfPseudoclass(name, "removed");
|
|
|
base.RemoveAt(index);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -224,6 +246,7 @@ namespace Avalonia.Controls
|
|
|
public override void RemoveRange(int index, int count)
|
|
|
{
|
|
|
base.RemoveRange(index, count);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -255,6 +278,7 @@ namespace Avalonia.Controls
|
|
|
}
|
|
|
|
|
|
base.AddRange(source);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
@@ -263,13 +287,38 @@ namespace Avalonia.Controls
|
|
|
if (!Contains(name))
|
|
|
{
|
|
|
base.Add(name);
|
|
|
+ NotifyChanged();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
bool IPseudoClasses.Remove(string name)
|
|
|
{
|
|
|
- return base.Remove(name);
|
|
|
+ if (base.Remove(name))
|
|
|
+ {
|
|
|
+ NotifyChanged();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ internal void AddListener(IClassesChangedListener listener)
|
|
|
+ {
|
|
|
+ (_listeners ??= new()).Add(listener);
|
|
|
+ }
|
|
|
+
|
|
|
+ internal void RemoveListener(IClassesChangedListener listener)
|
|
|
+ {
|
|
|
+ _listeners?.Remove(listener);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void NotifyChanged()
|
|
|
+ {
|
|
|
+ if (_listeners is null)
|
|
|
+ return;
|
|
|
+ foreach (var listener in _listeners)
|
|
|
+ listener.Changed();
|
|
|
}
|
|
|
|
|
|
private void ThrowIfPseudoclass(string name, string operation)
|