Browse Source

Avoid multiple resource change notifications (#18488)

Co-authored-by: Jumar Macato <16554748+jmacato@users.noreply.github.com>
pull/18558/head
Julien Lebosquain 11 months ago
committed by GitHub
parent
commit
d6718ec70b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      src/Avalonia.Base/Controls/IResourceHost.cs
  2. 17
      src/Avalonia.Base/Controls/ResourceDictionary.cs
  3. 40
      src/Avalonia.Base/Controls/ResourceNodeExtensions.cs
  4. 6
      src/Avalonia.Base/Controls/ResourceProvider.cs
  5. 1
      src/Avalonia.Base/Controls/ResourcesChangedEventArgs.cs
  6. 45
      src/Avalonia.Base/Controls/ResourcesChangedHelper.cs
  7. 11
      src/Avalonia.Base/Controls/ResourcesChangedToken.cs
  8. 48
      src/Avalonia.Base/StyledElement.cs
  9. 2
      src/Avalonia.Base/Styling/StyleBase.cs
  10. 6
      src/Avalonia.Base/Utilities/IWeakEventSubscriber.cs
  11. 4
      src/Avalonia.Base/Utilities/WeakEvent.cs
  12. 40
      src/Avalonia.Controls/Application.cs
  13. 6
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  14. 6
      src/Avalonia.Controls/Primitives/VisualLayerManager.cs
  15. 25
      src/Avalonia.Controls/TopLevel.cs
  16. 9
      src/Markup/Avalonia.Markup.Xaml/Data/DynamicResourceExpression.cs

8
src/Avalonia.Base/Controls/IResourceHost.cs

@ -29,4 +29,12 @@ namespace Avalonia.Controls
/// </remarks>
void NotifyHostedResourcesChanged(ResourcesChangedEventArgs e);
}
// TODO12: merge with IResourceHost
internal interface IResourceHost2 : IResourceHost
{
event EventHandler<ResourcesChangedToken> ResourcesChanged2;
void NotifyHostedResourcesChanged(ResourcesChangedToken token);
}
}

17
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<IServiceProvider?, object?> 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<KeyValuePair<object, object?>>)?.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());
}
}

40
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;

6
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());
}
/// <summary>
@ -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());
}
}

1
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();

45
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<ResourcesChangedEventArgs> handler,
EventHandler<ResourcesChangedToken> handler2)
{
if (host is IResourceHost2 host2)
host2.ResourcesChanged2 += handler2;
else
host.ResourcesChanged += handler;
}
internal static void UnsubscribeFromResourcesChanged(
this IResourceHost host,
EventHandler<ResourcesChangedEventArgs> handler,
EventHandler<ResourcesChangedToken> handler2)
{
if (host is IResourceHost2 host2)
host2.ResourcesChanged2 -= handler2;
else
host.ResourcesChanged -= handler;
}
}

11
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));
}

48
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<ResourcesChangedToken>? _resourcesChanged2;
private ResourcesChangedToken _lastResourcesChangedToken;
/// <summary>
/// Initializes static members of the <see cref="StyledElement"/> class.
@ -147,6 +150,12 @@ namespace Avalonia
/// </summary>
public event EventHandler<ResourcesChangedEventArgs>? ResourcesChanged;
event EventHandler<ResourcesChangedToken>? IResourceHost2.ResourcesChanged2
{
add => _resourcesChanged2 += value;
remove => _resourcesChanged2 -= value;
}
/// <inheritdoc />
public event EventHandler? ActualThemeVariantChanged;
@ -427,10 +436,15 @@ namespace Avalonia
}
/// <inheritdoc/>
void ILogical.NotifyResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e);
void ILogical.NotifyResourcesChanged(ResourcesChangedEventArgs e)
=> NotifyResourcesChanged(ResourcesChangedToken.Create());
/// <inheritdoc/>
void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e);
void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e)
=> NotifyResourcesChanged(ResourcesChangedToken.Create());
void IResourceHost2.NotifyHostedResourcesChanged(ResourcesChangedToken token)
=> NotifyResourcesChanged(token);
/// <inheritdoc/>
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
/// <summary>
/// Notifies child controls that a change has been made to resources that apply to them.
/// </summary>
/// <param name="e">The event args.</param>
internal virtual void NotifyChildResourcesChanged(ResourcesChangedEventArgs e)
/// <param name="token">The change token.</param>
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);
}
}

2
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());
}
}
}

6
src/Avalonia.Base/Utilities/IWeakEventSubscriber.cs

@ -6,12 +6,12 @@ namespace Avalonia.Utilities;
/// Defines a listener to a event subscribed vis the <see cref="WeakEvent{TTarget, TEventArgs}"/>.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event arguments.</typeparam>
public interface IWeakEventSubscriber<in TEventArgs> where TEventArgs : EventArgs
public interface IWeakEventSubscriber<in TEventArgs>
{
void OnEvent(object? sender, WeakEvent ev, TEventArgs e);
}
public sealed class WeakEventSubscriber<TEventArgs> : IWeakEventSubscriber<TEventArgs> where TEventArgs : EventArgs
public sealed class WeakEventSubscriber<TEventArgs> : IWeakEventSubscriber<TEventArgs>
{
public event Action<object?, WeakEvent, TEventArgs>? Event;
@ -21,7 +21,7 @@ public sealed class WeakEventSubscriber<TEventArgs> : IWeakEventSubscriber<TEven
}
}
public sealed class TargetWeakEventSubscriber<TTarget, TEventArgs> : IWeakEventSubscriber<TEventArgs> where TEventArgs : EventArgs
public sealed class TargetWeakEventSubscriber<TTarget, TEventArgs> : IWeakEventSubscriber<TEventArgs>
{
private readonly TTarget _target;
private readonly Action<TTarget, object?, WeakEvent, TEventArgs> _dispatchFunc;

4
src/Avalonia.Base/Utilities/WeakEvent.cs

@ -7,7 +7,7 @@ namespace Avalonia.Utilities;
/// <summary>
/// Manages subscriptions to events using weak listeners.
/// </summary>
public sealed class WeakEvent<TSender, TEventArgs> : WeakEvent where TEventArgs : EventArgs where TSender : class
public sealed class WeakEvent<TSender, TEventArgs> : WeakEvent where TSender : class
{
private readonly Func<TSender, EventHandler<TEventArgs>, Action> _subscribe;
@ -120,7 +120,7 @@ public class WeakEvent
{
public static WeakEvent<TSender, TEventArgs> Register<TSender, TEventArgs>(
Action<TSender, EventHandler<TEventArgs>> subscribe,
Action<TSender, EventHandler<TEventArgs>> unsubscribe) where TSender : class where TEventArgs : EventArgs
Action<TSender, EventHandler<TEventArgs>> unsubscribe) where TSender : class
{
return new WeakEvent<TSender, TEventArgs>(subscribe, unsubscribe);
}

40
src/Avalonia.Controls/Application.cs

@ -30,7 +30,7 @@ namespace Avalonia
/// method.
/// - Tracks the lifetime of the application.
/// </remarks>
public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IApplicationPlatformEvents, IOptionalFeatureProvider
public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IResourceHost2, IApplicationPlatformEvents, IOptionalFeatureProvider
{
/// <summary>
/// The application-global data templates.
@ -39,11 +39,11 @@ namespace Avalonia
private Styles? _styles;
private IResourceDictionary? _resources;
private bool _notifyingResourcesChanged;
private Action<IReadOnlyList<IStyle>>? _stylesAdded;
private Action<IReadOnlyList<IStyle>>? _stylesRemoved;
private IApplicationLifetime? _applicationLifetime;
private bool _setupCompleted;
private EventHandler<ResourcesChangedToken>? _resourcesChanged2;
/// <summary>
/// Defines the <see cref="DataContext"/> property.
@ -62,6 +62,12 @@ namespace Avalonia
/// <inheritdoc/>
public event EventHandler<ResourcesChangedEventArgs>? ResourcesChanged;
event EventHandler<ResourcesChangedToken>? IResourceHost2.ResourcesChanged2
{
add => _resourcesChanged2 += value;
remove => _resourcesChanged2 -= value;
}
[Obsolete("Use Application.Current.TryGetFeature<IActivatableLifetime>() instead.")]
public event EventHandler<UrlOpenedEventArgs>? 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<IStyle> 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;
/// <summary>
/// Defines Name property

6
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@ -348,7 +348,7 @@ namespace Avalonia.Controls.Primitives
}
/// <inheritdoc />
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);
}
/// <inheritdoc/>

6
src/Avalonia.Controls/Primitives/VisualLayerManager.cs

@ -118,12 +118,12 @@ namespace Avalonia.Controls.Primitives
}
/// <inheritdoc />
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);
}
/// <inheritdoc />

25
src/Avalonia.Controls/TopLevel.cs

@ -121,6 +121,12 @@ namespace Avalonia.Controls
(s, h) => s.ResourcesChanged -= h
);
private static readonly WeakEvent<IResourceHost2, ResourcesChangedToken>
ResourcesChanged2WeakEvent = WeakEvent.Register<IResourceHost2, ResourcesChangedToken>(
(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<TopLevel, ResourcesChangedEventArgs>? _resourcesChangesSubscriber;
private TargetWeakEventSubscriber<TopLevel, ResourcesChangedToken>? _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<TopLevel, ResourcesChangedToken>(
this, static (target, _, _, token) =>
{
target.NotifyResourcesChanged(token);
});
ResourcesChanged2WeakEvent.Subscribe(applicationResources2, _resourcesChangesSubscriber2);
}
else if (stylingParent is IResourceHost applicationResources)
{
_resourcesChangesSubscriber = new TargetWeakEventSubscriber<TopLevel, ResourcesChangedEventArgs>(
this, static (target, _, _, e) =>
this, static (target, _, _, _) =>
{
((ILogical)target).NotifyResourcesChanged(e);
target.NotifyResourcesChanged(ResourcesChangedToken.Create());
});
ResourcesChangedWeakEvent.Subscribe(applicationResources, _resourcesChangesSubscriber);

9
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;
}

Loading…
Cancel
Save