diff --git a/src/Avalonia.Base/Controls/IResourceHost.cs b/src/Avalonia.Base/Controls/IResourceHost.cs index 286f0e36ef..361e3562ec 100644 --- a/src/Avalonia.Base/Controls/IResourceHost.cs +++ b/src/Avalonia.Base/Controls/IResourceHost.cs @@ -29,4 +29,12 @@ namespace Avalonia.Controls /// void NotifyHostedResourcesChanged(ResourcesChangedEventArgs e); } + + // TODO12: merge with IResourceHost + internal interface IResourceHost2 : IResourceHost + { + event EventHandler ResourcesChanged2; + + void NotifyHostedResourcesChanged(ResourcesChangedToken token); + } } diff --git a/src/Avalonia.Base/Controls/ResourceDictionary.cs b/src/Avalonia.Base/Controls/ResourceDictionary.cs index ded0a815a5..e0944a5708 100644 --- a/src/Avalonia.Base/Controls/ResourceDictionary.cs +++ b/src/Avalonia.Base/Controls/ResourceDictionary.cs @@ -40,8 +40,7 @@ namespace Avalonia.Controls set { Inner[key] = value; - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); - + RaiseResourcesChanged(); } } @@ -139,7 +138,7 @@ namespace Avalonia.Controls public void Add(object key, object? value) { Inner.Add(key, value); - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + RaiseResourcesChanged(); } public void AddDeferred(object key, Func factory) @@ -160,7 +159,7 @@ namespace Avalonia.Controls } finally { - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + RaiseResourcesChanged(); } } @@ -169,7 +168,7 @@ namespace Avalonia.Controls if (_inner?.Count > 0) { _inner.Clear(); - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + RaiseResourcesChanged(); } } @@ -179,7 +178,7 @@ namespace Avalonia.Controls { if (_inner?.Remove(key) == true) { - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + RaiseResourcesChanged(); return true; } @@ -317,7 +316,7 @@ namespace Avalonia.Controls { if ((_inner as ICollection>)?.Remove(item) == true) { - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + RaiseResourcesChanged(); return true; } @@ -359,7 +358,7 @@ namespace Avalonia.Controls if (hasResources) { - owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + owner.NotifyHostedResourcesChanged(ResourcesChangedToken.Create()); } } @@ -386,7 +385,7 @@ namespace Avalonia.Controls if (hasResources) { - owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + owner.NotifyHostedResourcesChanged(ResourcesChangedToken.Create()); } } diff --git a/src/Avalonia.Base/Controls/ResourceNodeExtensions.cs b/src/Avalonia.Base/Controls/ResourceNodeExtensions.cs index f1a4a90864..36cc00d245 100644 --- a/src/Avalonia.Base/Controls/ResourceNodeExtensions.cs +++ b/src/Avalonia.Base/Controls/ResourceNodeExtensions.cs @@ -158,7 +158,8 @@ namespace Avalonia.Controls protected override void Initialize() { - _target.ResourcesChanged += ResourcesChanged; + _target.SubscribeToResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (_target is IThemeVariantHost themeVariantHost) { themeVariantHost.ActualThemeVariantChanged += ActualThemeVariantChanged; @@ -167,7 +168,8 @@ namespace Avalonia.Controls protected override void Deinitialize() { - _target.ResourcesChanged -= ResourcesChanged; + _target.UnsubscribeFromResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (_target is IThemeVariantHost themeVariantHost) { themeVariantHost.ActualThemeVariantChanged -= ActualThemeVariantChanged; @@ -184,6 +186,11 @@ namespace Avalonia.Controls PublishNext(GetValue()); } + private void ResourcesChanged2(object? sender, ResourcesChangedToken token) + { + PublishNext(GetValue()); + } + private void ActualThemeVariantChanged(object? sender, EventArgs e) { PublishNext(GetValue()); @@ -223,10 +230,8 @@ namespace Avalonia.Controls _target.OwnerChanged += OwnerChanged; _owner = _target.Owner; - if (_owner is not null) - { - _owner.ResourcesChanged += ResourcesChanged; - } + _owner?.SubscribeToResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (_overrideThemeVariant is null && _owner is IThemeVariantHost themeVariantHost) { themeVariantHost.ActualThemeVariantChanged += ActualThemeVariantChanged; @@ -237,10 +242,8 @@ namespace Avalonia.Controls { _target.OwnerChanged -= OwnerChanged; - if (_owner is not null) - { - _owner.ResourcesChanged -= ResourcesChanged; - } + _owner?.UnsubscribeFromResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (_overrideThemeVariant is null && _owner is IThemeVariantHost themeVariantHost) { themeVariantHost.ActualThemeVariantChanged -= ActualThemeVariantChanged; @@ -267,10 +270,8 @@ namespace Avalonia.Controls private void OwnerChanged(object? sender, EventArgs e) { - if (_owner is not null) - { - _owner.ResourcesChanged -= ResourcesChanged; - } + _owner?.UnsubscribeFromResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (_overrideThemeVariant is null && _owner is IThemeVariantHost themeVariantHost) { themeVariantHost.ActualThemeVariantChanged -= ActualThemeVariantChanged; @@ -278,10 +279,8 @@ namespace Avalonia.Controls _owner = _target.Owner; - if (_owner is not null) - { - _owner.ResourcesChanged += ResourcesChanged; - } + _owner?.SubscribeToResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (_overrideThemeVariant is null && _owner is IThemeVariantHost themeVariantHost2) { themeVariantHost2.ActualThemeVariantChanged += ActualThemeVariantChanged; @@ -300,6 +299,11 @@ namespace Avalonia.Controls PublishNext(); } + private void ResourcesChanged2(object? sender, ResourcesChangedToken token) + { + PublishNext(); + } + private object? GetValue() { var theme = _overrideThemeVariant ?? (_target.Owner as IThemeVariantHost)?.ActualThemeVariant; diff --git a/src/Avalonia.Base/Controls/ResourceProvider.cs b/src/Avalonia.Base/Controls/ResourceProvider.cs index 0760191d1e..f0ab42a4a8 100644 --- a/src/Avalonia.Base/Controls/ResourceProvider.cs +++ b/src/Avalonia.Base/Controls/ResourceProvider.cs @@ -45,7 +45,7 @@ public abstract class ResourceProvider : AvaloniaObject, IResourceProvider protected void RaiseResourcesChanged() { - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + Owner?.NotifyHostedResourcesChanged(ResourcesChangedToken.Create()); } /// @@ -57,7 +57,7 @@ public abstract class ResourceProvider : AvaloniaObject, IResourceProvider { if (HasResources) { - owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + owner.NotifyHostedResourcesChanged(ResourcesChangedToken.Create()); } } @@ -70,7 +70,7 @@ public abstract class ResourceProvider : AvaloniaObject, IResourceProvider { if (HasResources) { - owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + owner.NotifyHostedResourcesChanged(ResourcesChangedToken.Create()); } } diff --git a/src/Avalonia.Base/Controls/ResourcesChangedEventArgs.cs b/src/Avalonia.Base/Controls/ResourcesChangedEventArgs.cs index ee2ece8a26..a60c95a2e0 100644 --- a/src/Avalonia.Base/Controls/ResourcesChangedEventArgs.cs +++ b/src/Avalonia.Base/Controls/ResourcesChangedEventArgs.cs @@ -2,6 +2,7 @@ namespace Avalonia.Controls { + // TODO12: change this to be a struct, remove ResourcesChangedToken public class ResourcesChangedEventArgs : EventArgs { public static new readonly ResourcesChangedEventArgs Empty = new ResourcesChangedEventArgs(); diff --git a/src/Avalonia.Base/Controls/ResourcesChangedHelper.cs b/src/Avalonia.Base/Controls/ResourcesChangedHelper.cs new file mode 100644 index 0000000000..8ad121ad3a --- /dev/null +++ b/src/Avalonia.Base/Controls/ResourcesChangedHelper.cs @@ -0,0 +1,45 @@ +using System; +using Avalonia.LogicalTree; + +namespace Avalonia.Controls; + +internal static class ResourcesChangedHelper +{ + internal static void NotifyHostedResourcesChanged(this IResourceHost host, ResourcesChangedToken token) + { + if (host is IResourceHost2 host2) + host2.NotifyHostedResourcesChanged(token); + else + host.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + } + + internal static void NotifyResourcesChanged(this ILogical logical, ResourcesChangedToken token) + { + if (logical is StyledElement styledElement) + styledElement.NotifyResourcesChanged(token); + else + logical.NotifyResourcesChanged(ResourcesChangedEventArgs.Empty); + } + + internal static void SubscribeToResourcesChanged( + this IResourceHost host, + EventHandler handler, + EventHandler handler2) + { + if (host is IResourceHost2 host2) + host2.ResourcesChanged2 += handler2; + else + host.ResourcesChanged += handler; + } + + internal static void UnsubscribeFromResourcesChanged( + this IResourceHost host, + EventHandler handler, + EventHandler handler2) + { + if (host is IResourceHost2 host2) + host2.ResourcesChanged2 -= handler2; + else + host.ResourcesChanged -= handler; + } +} diff --git a/src/Avalonia.Base/Controls/ResourcesChangedToken.cs b/src/Avalonia.Base/Controls/ResourcesChangedToken.cs new file mode 100644 index 0000000000..8de692e729 --- /dev/null +++ b/src/Avalonia.Base/Controls/ResourcesChangedToken.cs @@ -0,0 +1,11 @@ +using System.Threading; + +namespace Avalonia.Controls; + +internal record struct ResourcesChangedToken(int SequenceNumber) +{ + private static int s_lastSequenceNumber; + + public static ResourcesChangedToken Create() + => new(Interlocked.Increment(ref s_lastSequenceNumber)); +} diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs index 3e57a1a959..3d4a4efb92 100644 --- a/src/Avalonia.Base/StyledElement.cs +++ b/src/Avalonia.Base/StyledElement.cs @@ -29,6 +29,7 @@ namespace Avalonia IDataContextProvider, ILogical, IThemeVariantHost, + IResourceHost2, IStyleHost, ISetLogicalParent, ISetInheritanceParent, @@ -93,6 +94,8 @@ namespace Avalonia private AvaloniaObject? _templatedParent; private bool _dataContextUpdating; private ControlTheme? _implicitTheme; + private EventHandler? _resourcesChanged2; + private ResourcesChangedToken _lastResourcesChangedToken; /// /// Initializes static members of the class. @@ -147,6 +150,12 @@ namespace Avalonia /// public event EventHandler? ResourcesChanged; + event EventHandler? IResourceHost2.ResourcesChanged2 + { + add => _resourcesChanged2 += value; + remove => _resourcesChanged2 -= value; + } + /// public event EventHandler? ActualThemeVariantChanged; @@ -427,10 +436,15 @@ namespace Avalonia } /// - void ILogical.NotifyResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e); + void ILogical.NotifyResourcesChanged(ResourcesChangedEventArgs e) + => NotifyResourcesChanged(ResourcesChangedToken.Create()); /// - void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e); + void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e) + => NotifyResourcesChanged(ResourcesChangedToken.Create()); + + void IResourceHost2.NotifyHostedResourcesChanged(ResourcesChangedToken token) + => NotifyResourcesChanged(token); /// public bool TryGetResource(object key, ThemeVariant? theme, out object? value) @@ -485,7 +499,7 @@ namespace Avalonia // non-rooted control beacuse it's unlikely that dynamic resources need to be // correct until the control is added to the tree, and it causes a *lot* of // notifications. - NotifyResourcesChanged(); + NotifyResourcesChanged(ResourcesChangedToken.Create()); } RaisePropertyChanged(ParentProperty, old, Parent); @@ -538,8 +552,8 @@ namespace Avalonia /// /// Notifies child controls that a change has been made to resources that apply to them. /// - /// The event args. - internal virtual void NotifyChildResourcesChanged(ResourcesChangedEventArgs e) + /// The change token. + internal virtual void NotifyChildResourcesChanged(ResourcesChangedToken token) { if (_logicalChildren is object) { @@ -547,11 +561,9 @@ namespace Avalonia if (count > 0) { - e ??= ResourcesChangedEventArgs.Empty; - for (var i = 0; i < count; ++i) { - _logicalChildren[i].NotifyResourcesChanged(e); + _logicalChildren[i].NotifyResourcesChanged(token); } } } @@ -880,7 +892,7 @@ namespace Avalonia ReevaluateImplicitTheme(); ApplyStyling(); - NotifyResourcesChanged(propagate: false); + NotifyResourcesChanged(ResourcesChangedToken.Create(), propagate: false); OnAttachedToLogicalTree(e); AttachedToLogicalTree?.Invoke(this, e); @@ -983,20 +995,24 @@ namespace Avalonia } } - private void NotifyResourcesChanged( - ResourcesChangedEventArgs? e = null, + internal void NotifyResourcesChanged( + ResourcesChangedToken token, bool propagate = true) { - if (ResourcesChanged is object) + // We already got a notification for this element, ignore. + if (token.Equals(_lastResourcesChangedToken)) { - e ??= ResourcesChangedEventArgs.Empty; - ResourcesChanged(this, e); + return; } + _lastResourcesChangedToken = token; + + _resourcesChanged2?.Invoke(this, token); + ResourcesChanged?.Invoke(this, ResourcesChangedEventArgs.Empty); + if (propagate) { - e ??= ResourcesChangedEventArgs.Empty; - NotifyChildResourcesChanged(e); + NotifyChildResourcesChanged(token); } } diff --git a/src/Avalonia.Base/Styling/StyleBase.cs b/src/Avalonia.Base/Styling/StyleBase.cs index bc3457cb48..3b12fda731 100644 --- a/src/Avalonia.Base/Styling/StyleBase.cs +++ b/src/Avalonia.Base/Styling/StyleBase.cs @@ -54,7 +54,7 @@ namespace Avalonia.Styling if (hadResources || _resources.HasResources) { - Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + Owner.NotifyHostedResourcesChanged(ResourcesChangedToken.Create()); } } } diff --git a/src/Avalonia.Base/Utilities/IWeakEventSubscriber.cs b/src/Avalonia.Base/Utilities/IWeakEventSubscriber.cs index 6cf8c605a7..309146b7f1 100644 --- a/src/Avalonia.Base/Utilities/IWeakEventSubscriber.cs +++ b/src/Avalonia.Base/Utilities/IWeakEventSubscriber.cs @@ -6,12 +6,12 @@ namespace Avalonia.Utilities; /// Defines a listener to a event subscribed vis the . /// /// The type of the event arguments. -public interface IWeakEventSubscriber where TEventArgs : EventArgs +public interface IWeakEventSubscriber { void OnEvent(object? sender, WeakEvent ev, TEventArgs e); } -public sealed class WeakEventSubscriber : IWeakEventSubscriber where TEventArgs : EventArgs +public sealed class WeakEventSubscriber : IWeakEventSubscriber { public event Action? Event; @@ -21,7 +21,7 @@ public sealed class WeakEventSubscriber : IWeakEventSubscriber : IWeakEventSubscriber where TEventArgs : EventArgs +public sealed class TargetWeakEventSubscriber : IWeakEventSubscriber { private readonly TTarget _target; private readonly Action _dispatchFunc; diff --git a/src/Avalonia.Base/Utilities/WeakEvent.cs b/src/Avalonia.Base/Utilities/WeakEvent.cs index a8e6e6191f..bc7cd04568 100644 --- a/src/Avalonia.Base/Utilities/WeakEvent.cs +++ b/src/Avalonia.Base/Utilities/WeakEvent.cs @@ -7,7 +7,7 @@ namespace Avalonia.Utilities; /// /// Manages subscriptions to events using weak listeners. /// -public sealed class WeakEvent : WeakEvent where TEventArgs : EventArgs where TSender : class +public sealed class WeakEvent : WeakEvent where TSender : class { private readonly Func, Action> _subscribe; @@ -120,7 +120,7 @@ public class WeakEvent { public static WeakEvent Register( Action> subscribe, - Action> unsubscribe) where TSender : class where TEventArgs : EventArgs + Action> unsubscribe) where TSender : class { return new WeakEvent(subscribe, unsubscribe); } diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index e48711efdb..1af3f20c2e 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -30,7 +30,7 @@ namespace Avalonia /// method. /// - Tracks the lifetime of the application. /// - public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IApplicationPlatformEvents, IOptionalFeatureProvider + public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IResourceHost2, IApplicationPlatformEvents, IOptionalFeatureProvider { /// /// The application-global data templates. @@ -39,11 +39,11 @@ namespace Avalonia private Styles? _styles; private IResourceDictionary? _resources; - private bool _notifyingResourcesChanged; private Action>? _stylesAdded; private Action>? _stylesRemoved; private IApplicationLifetime? _applicationLifetime; private bool _setupCompleted; + private EventHandler? _resourcesChanged2; /// /// Defines the property. @@ -62,6 +62,12 @@ namespace Avalonia /// public event EventHandler? ResourcesChanged; + event EventHandler? IResourceHost2.ResourcesChanged2 + { + add => _resourcesChanged2 += value; + remove => _resourcesChanged2 -= value; + } + [Obsolete("Use Application.Current.TryGetFeature() instead.")] public event EventHandler? UrlsOpened; @@ -233,9 +239,16 @@ namespace Avalonia void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e) { + _resourcesChanged2?.Invoke(this, ResourcesChangedToken.Create()); ResourcesChanged?.Invoke(this, e); } + void IResourceHost2.NotifyHostedResourcesChanged(ResourcesChangedToken token) + { + _resourcesChanged2?.Invoke(this, token); + ResourcesChanged?.Invoke(this, ResourcesChangedEventArgs.Empty); + } + void IStyleHost.StylesAdded(IReadOnlyList styles) { _stylesAdded?.Invoke(styles); @@ -292,29 +305,6 @@ namespace Avalonia UrlsOpened?.Invoke(this, new UrlOpenedEventArgs (urls)); } - private void NotifyResourcesChanged(ResourcesChangedEventArgs e) - { - if (_notifyingResourcesChanged) - { - return; - } - - try - { - _notifyingResourcesChanged = true; - ResourcesChanged?.Invoke(this, ResourcesChangedEventArgs.Empty); - } - finally - { - _notifyingResourcesChanged = false; - } - } - - private void ThisResourcesChanged(object sender, ResourcesChangedEventArgs e) - { - NotifyResourcesChanged(e); - } - private string? _name; /// /// Defines Name property diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs index 12b631aeb1..b6bf9be866 100644 --- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs +++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs @@ -348,7 +348,7 @@ namespace Avalonia.Controls.Primitives } /// - internal sealed override void NotifyChildResourcesChanged(ResourcesChangedEventArgs e) + internal sealed override void NotifyChildResourcesChanged(ResourcesChangedToken token) { var count = VisualChildren.Count; @@ -356,11 +356,11 @@ namespace Avalonia.Controls.Primitives { if (VisualChildren[i] is ILogical logical) { - logical.NotifyResourcesChanged(e); + logical.NotifyResourcesChanged(token); } } - base.NotifyChildResourcesChanged(e); + base.NotifyChildResourcesChanged(token); } /// diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs index 889662f02c..2e1b9a59fb 100644 --- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs +++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs @@ -118,12 +118,12 @@ namespace Avalonia.Controls.Primitives } /// - internal override void NotifyChildResourcesChanged(ResourcesChangedEventArgs e) + internal override void NotifyChildResourcesChanged(ResourcesChangedToken token) { foreach (var l in _layers) - ((ILogical)l).NotifyResourcesChanged(e); + l.NotifyResourcesChanged(token); - base.NotifyChildResourcesChanged(e); + base.NotifyChildResourcesChanged(token); } /// diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 3a71b32685..71e56e7d78 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -121,6 +121,12 @@ namespace Avalonia.Controls (s, h) => s.ResourcesChanged -= h ); + private static readonly WeakEvent + ResourcesChanged2WeakEvent = WeakEvent.Register( + (s, h) => s.ResourcesChanged2 += h, + (s, h) => s.ResourcesChanged2 -= h + ); + private readonly IInputManager? _inputManager; private readonly IToolTipService? _tooltipService; private readonly IAccessKeyHandler? _accessKeyHandler; @@ -137,6 +143,7 @@ namespace Avalonia.Controls private ILayoutManager? _layoutManager; private Border? _transparencyFallbackBorder; private TargetWeakEventSubscriber? _resourcesChangesSubscriber; + private TargetWeakEventSubscriber? _resourcesChangesSubscriber2; private IStorageProvider? _storageProvider; private Screens? _screens; private LayoutDiagnosticBridge? _layoutDiagnosticBridge; @@ -257,12 +264,24 @@ namespace Avalonia.Controls ClientSize = impl.ClientSize; - if (((IStyleHost)this).StylingParent is IResourceHost applicationResources) + var stylingParent = ((IStyleHost)this).StylingParent; + + if (stylingParent is IResourceHost2 applicationResources2) + { + _resourcesChangesSubscriber2 = new TargetWeakEventSubscriber( + this, static (target, _, _, token) => + { + target.NotifyResourcesChanged(token); + }); + + ResourcesChanged2WeakEvent.Subscribe(applicationResources2, _resourcesChangesSubscriber2); + } + else if (stylingParent is IResourceHost applicationResources) { _resourcesChangesSubscriber = new TargetWeakEventSubscriber( - this, static (target, _, _, e) => + this, static (target, _, _, _) => { - ((ILogical)target).NotifyResourcesChanged(e); + target.NotifyResourcesChanged(ResourcesChangedToken.Create()); }); ResourcesChangedWeakEvent.Subscribe(applicationResources, _resourcesChangesSubscriber); diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/DynamicResourceExpression.cs b/src/Markup/Avalonia.Markup.Xaml/Data/DynamicResourceExpression.cs index 438c140395..e65282b36b 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Data/DynamicResourceExpression.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Data/DynamicResourceExpression.cs @@ -84,6 +84,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions private void ResourcesChanged(object? sender, ResourcesChangedEventArgs e) => PublishValue(); + private void ResourcesChanged2(object? sender, ResourcesChangedToken token) => PublishValue(); + private void ActualThemeVariantChanged(object? sender, EventArgs e) { if (!IsRunning) @@ -132,8 +134,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions { if (host is not null) { - host.ResourcesChanged += ResourcesChanged; - + host.SubscribeToResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (!_overrideThemeVariant && _host is IThemeVariantHost themeVariantHost) { _themeVariant = themeVariantHost.ActualThemeVariant; @@ -146,7 +148,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions { if (host is not null) { - host.ResourcesChanged -= ResourcesChanged; + host.UnsubscribeFromResourcesChanged(ResourcesChanged, ResourcesChanged2); + if (!_overrideThemeVariant && _host is IThemeVariantHost themeVariantHost) themeVariantHost.ActualThemeVariantChanged -= ActualThemeVariantChanged; }