diff --git a/src/Avalonia.Base/Styling/Style.cs b/src/Avalonia.Base/Styling/Style.cs
index 000e588bad..c85c85fe21 100644
--- a/src/Avalonia.Base/Styling/Style.cs
+++ b/src/Avalonia.Base/Styling/Style.cs
@@ -1,23 +1,12 @@
using System;
-using System.Collections.Generic;
-using Avalonia.Animation;
-using Avalonia.Controls;
-using Avalonia.Metadata;
namespace Avalonia.Styling
{
///
/// Defines a style.
///
- public class Style : AvaloniaObject, IStyle, IResourceProvider
+ public class Style : StyleBase
{
- private IResourceHost? _owner;
- private StyleChildren? _children;
- private IResourceDictionary? _resources;
- private List? _setters;
- private List? _animations;
- private StyleCache? _childCache;
-
///
/// Initializes a new instance of the class.
///
@@ -34,114 +23,11 @@ namespace Avalonia.Styling
Selector = selector(null);
}
- ///
- /// Gets the children of the style.
- ///
- public IList Children => _children ??= new(this);
-
- ///
- /// Gets the or Application that hosts the style.
- ///
- public IResourceHost? Owner
- {
- get => _owner;
- private set
- {
- if (_owner != value)
- {
- _owner = value;
- OwnerChanged?.Invoke(this, EventArgs.Empty);
- }
- }
- }
-
- ///
- /// Gets the parent style if this style is hosted in a collection.
- ///
- public Style? Parent { get; private set; }
-
- ///
- /// Gets or sets a dictionary of style resources.
- ///
- public IResourceDictionary Resources
- {
- get => _resources ?? (Resources = new ResourceDictionary());
- set
- {
- value = value ?? throw new ArgumentNullException(nameof(value));
-
- var hadResources = _resources?.HasResources ?? false;
-
- _resources = value;
-
- if (Owner is object)
- {
- _resources.AddOwner(Owner);
-
- if (hadResources || _resources.HasResources)
- {
- Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
- }
- }
- }
- }
-
///
/// Gets or sets the style's selector.
///
public Selector? Selector { get; set; }
- ///
- /// Gets the style's setters.
- ///
- public IList Setters => _setters ??= new List();
-
- ///
- /// Gets the style's animations.
- ///
- public IList Animations => _animations ??= new List();
-
- bool IResourceNode.HasResources => _resources?.Count > 0;
- IReadOnlyList IStyle.Children => (IReadOnlyList?)_children ?? Array.Empty();
-
- public event EventHandler? OwnerChanged;
-
- public void Add(ISetter setter) => Setters.Add(setter);
- public void Add(IStyle style) => Children.Add(style);
-
- public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
- {
- target = target ?? throw new ArgumentNullException(nameof(target));
-
- var match = Selector is object ? Selector.Match(target, Parent) :
- target == host ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance;
-
- if (match.IsMatch && (_setters is object || _animations is object))
- {
- var instance = new StyleInstance(this, target, _setters, _animations, match.Activator);
- target.StyleApplied(instance);
- instance.Start();
- }
-
- var result = match.Result;
-
- if (_children is not null)
- {
- _childCache ??= new StyleCache();
- var childResult = _childCache.TryAttach(_children, target, host);
- if (childResult > result)
- result = childResult;
- }
-
- return result;
- }
-
- public bool TryGetResource(object key, out object? result)
- {
- result = null;
- return _resources?.TryGetResource(key, out result) ?? false;
- }
-
///
/// Returns a string representation of the style.
///
@@ -158,33 +44,17 @@ namespace Avalonia.Styling
}
}
- void IResourceProvider.AddOwner(IResourceHost owner)
- {
- owner = owner ?? throw new ArgumentNullException(nameof(owner));
-
- if (Owner != null)
- {
- throw new InvalidOperationException("The Style already has a parent.");
- }
-
- Owner = owner;
- _resources?.AddOwner(owner);
- }
-
- void IResourceProvider.RemoveOwner(IResourceHost owner)
+ protected override SelectorMatch Matches(IStyleable target, IStyleHost? host)
{
- owner = owner ?? throw new ArgumentNullException(nameof(owner));
-
- if (Owner == owner)
- {
- Owner = null;
- _resources?.RemoveOwner(owner);
- }
+ return Selector?.Match(target, Parent) ??
+ (target == host ?
+ SelectorMatch.AlwaysThisInstance :
+ SelectorMatch.NeverThisInstance);
}
- internal void SetParent(Style? parent)
+ internal override void SetParent(StyleBase? parent)
{
- if (parent?.Selector is not null)
+ if (parent is Style parentStyle && parentStyle.Selector is not null)
{
if (Selector is null)
throw new InvalidOperationException("Child styles must have a selector.");
@@ -192,7 +62,7 @@ namespace Avalonia.Styling
throw new InvalidOperationException("Child styles must have a nesting selector.");
}
- Parent = parent;
+ base.SetParent(parent);
}
}
}
diff --git a/src/Avalonia.Base/Styling/StyleBase.cs b/src/Avalonia.Base/Styling/StyleBase.cs
new file mode 100644
index 0000000000..0fc57da728
--- /dev/null
+++ b/src/Avalonia.Base/Styling/StyleBase.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Animation;
+using Avalonia.Controls;
+using Avalonia.Metadata;
+
+namespace Avalonia.Styling
+{
+ ///
+ /// Base class for and .
+ ///
+ public abstract class StyleBase : AvaloniaObject, IStyle, IResourceProvider
+ {
+ private IResourceHost? _owner;
+ private StyleChildren? _children;
+ private IResourceDictionary? _resources;
+ private List? _setters;
+ private List? _animations;
+ private StyleCache? _childCache;
+
+ public IList Children => _children ??= new(this);
+
+ public IResourceHost? Owner
+ {
+ get => _owner;
+ private set
+ {
+ if (_owner != value)
+ {
+ _owner = value;
+ OwnerChanged?.Invoke(this, EventArgs.Empty);
+ }
+ }
+ }
+
+ public IStyle? Parent { get; private set; }
+
+ public IResourceDictionary Resources
+ {
+ get => _resources ?? (Resources = new ResourceDictionary());
+ set
+ {
+ value = value ?? throw new ArgumentNullException(nameof(value));
+
+ var hadResources = _resources?.HasResources ?? false;
+
+ _resources = value;
+
+ if (Owner is object)
+ {
+ _resources.AddOwner(Owner);
+
+ if (hadResources || _resources.HasResources)
+ {
+ Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
+ }
+ }
+ }
+ }
+
+ public IList Setters => _setters ??= new List();
+ public IList Animations => _animations ??= new List();
+
+ bool IResourceNode.HasResources => _resources?.Count > 0;
+ IReadOnlyList IStyle.Children => (IReadOnlyList?)_children ?? Array.Empty();
+
+ public void Add(ISetter setter) => Setters.Add(setter);
+ public void Add(IStyle style) => Children.Add(style);
+
+ public event EventHandler? OwnerChanged;
+
+ public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
+ {
+ target = target ?? throw new ArgumentNullException(nameof(target));
+
+ var result = SelectorMatchResult.NeverThisType;
+
+ if (_setters?.Count > 0 || _animations?.Count > 0)
+ {
+ var match = Matches(target, host);
+
+ if (match.IsMatch)
+ {
+ var instance = new StyleInstance(this, target, _setters, _animations, match.Activator);
+ target.StyleApplied(instance);
+ instance.Start();
+ }
+
+ result = match.Result;
+ }
+
+ if (_children is not null)
+ {
+ _childCache ??= new StyleCache();
+ var childResult = _childCache.TryAttach(_children, target, host);
+ if (childResult > result)
+ result = childResult;
+ }
+
+ return result;
+ }
+
+ public bool TryGetResource(object key, out object? result)
+ {
+ result = null;
+ return _resources?.TryGetResource(key, out result) ?? false;
+ }
+
+ protected abstract SelectorMatch Matches(IStyleable target, IStyleHost? host);
+
+ internal virtual void SetParent(StyleBase? parent) => Parent = parent;
+
+ void IResourceProvider.AddOwner(IResourceHost owner)
+ {
+ owner = owner ?? throw new ArgumentNullException(nameof(owner));
+
+ if (Owner != null)
+ {
+ throw new InvalidOperationException("The Style already has a parent.");
+ }
+
+ Owner = owner;
+ _resources?.AddOwner(owner);
+ }
+
+ void IResourceProvider.RemoveOwner(IResourceHost owner)
+ {
+ owner = owner ?? throw new ArgumentNullException(nameof(owner));
+
+ if (Owner == owner)
+ {
+ Owner = null;
+ _resources?.RemoveOwner(owner);
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.Base/Styling/StyleChildren.cs b/src/Avalonia.Base/Styling/StyleChildren.cs
index 5f8635f155..42b0a331ee 100644
--- a/src/Avalonia.Base/Styling/StyleChildren.cs
+++ b/src/Avalonia.Base/Styling/StyleChildren.cs
@@ -5,20 +5,20 @@ namespace Avalonia.Styling
{
internal class StyleChildren : Collection
{
- private readonly Style _owner;
+ private readonly StyleBase _owner;
- public StyleChildren(Style owner) => _owner = owner;
+ public StyleChildren(StyleBase owner) => _owner = owner;
protected override void InsertItem(int index, IStyle item)
{
- (item as Style)?.SetParent(_owner);
+ (item as StyleBase)?.SetParent(_owner);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
var item = Items[index];
- (item as Style)?.SetParent(null);
+ (item as StyleBase)?.SetParent(null);
if (_owner.Owner is IResourceHost host)
(item as IResourceProvider)?.RemoveOwner(host);
base.RemoveItem(index);
@@ -26,7 +26,7 @@ namespace Avalonia.Styling
protected override void SetItem(int index, IStyle item)
{
- (item as Style)?.SetParent(_owner);
+ (item as StyleBase)?.SetParent(_owner);
base.SetItem(index, item);
if (_owner.Owner is IResourceHost host)
(item as IResourceProvider)?.AddOwner(host);