diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs
index 02f47e07b4..3bf72460df 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, IResourceNode
+ public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IResourceHost
{
///
/// The application-global data templates.
@@ -129,26 +129,13 @@ namespace Avalonia
///
public IResourceDictionary Resources
{
- get => _resources ?? (Resources = new ResourceDictionary());
+ get => _resources ??= new ResourceDictionary(this);
set
{
- Contract.Requires(value != null);
-
- var hadResources = false;
-
- if (_resources != null)
- {
- hadResources = _resources.Count > 0;
- _resources.ResourcesChanged -= ThisResourcesChanged;
- }
-
+ value = value ?? throw new ArgumentNullException(nameof(value));
+ _resources?.RemoveOwner(this);
_resources = value;
- _resources.ResourcesChanged += ThisResourcesChanged;
-
- if (hadResources || _resources.Count > 0)
- {
- ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs());
- }
+ _resources.AddOwner(this);
}
}
@@ -161,23 +148,15 @@ namespace Avalonia
///
/// Global styles apply to all windows in the application.
///
- public Styles Styles
- {
- get
- {
- if (_styles == null)
- {
- _styles = new Styles(this);
- _styles.ResourcesChanged += ThisResourcesChanged;
- }
-
- return _styles;
- }
- }
+ public Styles Styles => _styles ??= new Styles(this);
///
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
+ ///
+ bool IResourceNode.HasResources => (_resources?.HasResources ?? false) ||
+ (((IResourceNode?)_styles)?.HasResources ?? false);
+
///
/// Gets the styling parent of the application, which is null.
///
@@ -185,13 +164,7 @@ namespace Avalonia
///
bool IStyleHost.IsStylesInitialized => _styles != null;
-
- ///
- bool IResourceProvider.HasResources => _resources?.Count > 0;
-
- ///
- IResourceNode IResourceNode.ResourceParent => null;
-
+
///
/// Application lifetime, use it for things like setting the main window and exiting the app from code
/// Currently supported lifetimes are:
@@ -219,13 +192,18 @@ namespace Avalonia
public virtual void Initialize() { }
///
- bool IResourceProvider.TryGetResource(object key, out object value)
+ bool IResourceNode.TryGetResource(object key, out object value)
{
value = null;
return (_resources?.TryGetResource(key, out value) ?? false) ||
Styles.TryGetResource(key, out value);
}
+ void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e)
+ {
+ ResourcesChanged?.Invoke(this, e);
+ }
+
void IStyleHost.StylesAdded(IReadOnlyList styles)
{
_stylesAdded?.Invoke(styles);
@@ -282,9 +260,7 @@ namespace Avalonia
try
{
_notifyingResourcesChanged = true;
- (_resources as ISetResourceParent)?.ParentResourcesChanged(e);
- (_styles as ISetResourceParent)?.ParentResourcesChanged(e);
- ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs());
+ ResourcesChanged?.Invoke(this, ResourcesChangedEventArgs.Empty);
}
finally
{
diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
index 97d01a38bd..820d5777f5 100644
--- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs
+++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
@@ -287,6 +287,21 @@ namespace Avalonia.Controls.Primitives
return this;
}
+ protected sealed override void NotifyChildResourcesChanged(ResourcesChangedEventArgs e)
+ {
+ var count = VisualChildren.Count;
+
+ for (var i = 0; i < count; ++i)
+ {
+ if (VisualChildren[i] is ILogical logical)
+ {
+ logical.NotifyResourcesChanged(e);
+ }
+ }
+
+ base.NotifyChildResourcesChanged(e);
+ }
+
///
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
index 385e7cc567..86aeb5c62a 100644
--- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
+++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
@@ -55,8 +55,15 @@ namespace Avalonia.Controls.Primitives
((ILogical)layer).NotifyAttachedToLogicalTree(new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this));
InvalidateArrange();
}
-
-
+
+ protected override void NotifyChildResourcesChanged(ResourcesChangedEventArgs e)
+ {
+ foreach (var l in _layers)
+ ((ILogical)l).NotifyResourcesChanged(e);
+
+ base.NotifyChildResourcesChanged(e);
+ }
+
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
@@ -74,7 +81,6 @@ namespace Avalonia.Controls.Primitives
((ILogical)l).NotifyDetachedFromLogicalTree(e);
}
-
protected override Size MeasureOverride(Size availableSize)
{
foreach (var l in _layers)
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index 1bf33acf42..6c09420f35 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -157,11 +157,11 @@ namespace Avalonia.Controls
x => (x as InputElement)?.GetObservable(CursorProperty) ?? Observable.Empty())
.Switch().Subscribe(cursor => PlatformImpl?.SetCursor(cursor?.PlatformCursor));
- if (((IStyleHost)this).StylingParent is IResourceProvider applicationResources)
+ if (((IStyleHost)this).StylingParent is IResourceHost applicationResources)
{
WeakSubscriptionManager.Subscribe(
applicationResources,
- nameof(IResourceProvider.ResourcesChanged),
+ nameof(IResourceHost.ResourcesChanged),
this);
}
}
diff --git a/src/Avalonia.Styling/Controls/IResourceDictionary.cs b/src/Avalonia.Styling/Controls/IResourceDictionary.cs
index 240f9b08bf..3a68dde31e 100644
--- a/src/Avalonia.Styling/Controls/IResourceDictionary.cs
+++ b/src/Avalonia.Styling/Controls/IResourceDictionary.cs
@@ -1,11 +1,13 @@
using System.Collections.Generic;
+#nullable enable
+
namespace Avalonia.Controls
{
///
/// An indexed dictionary of resources.
///
- public interface IResourceDictionary : IResourceProvider, IDictionary