From 56c098f77e04007bd039c69e50c8179cf144ee60 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 20 Jul 2022 16:42:09 +0200 Subject: [PATCH] Use shared StyleInstance if possible. If a `StyleBase` has no activator, and its `Setter`s don't need to be separately instanced on the control, then we can share a `StyleInstance` between controls. This causes failing tests because `TopLevel` applies styles in its constructor, but doesn't set `_styled` to true, meaning that styles get applied twice. This issue will need to be addressed separately. --- src/Avalonia.Base/Styling/StyleBase.cs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Base/Styling/StyleBase.cs b/src/Avalonia.Base/Styling/StyleBase.cs index 5e6cc650a4..1300eb3ba8 100644 --- a/src/Avalonia.Base/Styling/StyleBase.cs +++ b/src/Avalonia.Base/Styling/StyleBase.cs @@ -19,6 +19,7 @@ namespace Avalonia.Styling private List? _setters; private List? _animations; private StyleCache? _childCache; + private StyleInstance? _sharedInstance; public IList Children => _children ??= new(this); @@ -86,15 +87,30 @@ namespace Avalonia.Styling if (target is not AvaloniaObject ao) throw new InvalidOperationException("Styles can only be applied to AvaloniaObjects."); - var instance = new StyleInstance(this, activator); + StyleInstance instance; - if (_setters is object) + if (_sharedInstance is not null) { - foreach (var setter in _setters) + instance = _sharedInstance; + } + else + { + var canShareInstance = activator is null; + + instance = new StyleInstance(this, activator); + + if (_setters is object) { - var setterInstance = setter.Instance(instance, target); - instance.Add(setterInstance); + foreach (var setter in _setters) + { + var setterInstance = setter.Instance(instance, target); + instance.Add(setterInstance); + canShareInstance &= setterInstance == setter; + } } + + if (canShareInstance) + _sharedInstance = instance; } ao.GetValueStore().AddFrame(instance);