diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 5102c9a952..8c5f9abb8d 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -39,7 +39,7 @@ namespace Avalonia private readonly Lazy _clipboard = new Lazy(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))); private readonly Styler _styler = new Styler(); - private ResourceDictionary _resources; + private IResourceDictionary _resources; /// /// Initializes a new instance of the class. @@ -107,7 +107,30 @@ namespace Avalonia /// /// Gets the application's global resource dictionary. /// - public IResourceDictionary Resources => _resources ?? (_resources = new ResourceDictionary()); + public IResourceDictionary Resources + { + get => _resources ?? (Resources = new ResourceDictionary()); + set + { + Contract.Requires(value != null); + + var hadResources = false; + + if (_resources != null) + { + hadResources = _resources.Count > 0; + _resources.ResourcesChanged -= ResourcesChanged; + } + + _resources = value; + _resources.ResourcesChanged += ResourcesChanged; + + if (hadResources || _resources.Count > 0) + { + ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs()); + } + } + } /// /// Gets the application's global styles. diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index a05dccec58..bde9bb6760 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -97,7 +97,7 @@ namespace Avalonia.Controls private bool _isAttachedToLogicalTree; private IAvaloniaList _logicalChildren; private INameScope _nameScope; - private ResourceDictionary _resources; + private IResourceDictionary _resources; private Styles _styles; private bool _styled; private Subject _styleDetach = new Subject(); @@ -318,15 +318,26 @@ namespace Avalonia.Controls /// public IResourceDictionary Resources { - get + get => _resources ?? (Resources = new ResourceDictionary()); + set { - if (_resources == null) + Contract.Requires(value != null); + + var hadResources = false; + + if (_resources != null) { - _resources = new ResourceDictionary(); - _resources.ResourcesChanged += ThisResourcesChanged; + hadResources = _resources.Count > 0; + _resources.ResourcesChanged -= ThisResourcesChanged; } - return _resources; + _resources = value; + _resources.ResourcesChanged += ThisResourcesChanged; + + if (hadResources || _resources.Count > 0) + { + ((ILogical)this).NotifyResourcesChanged(new ResourcesChangedEventArgs()); + } } } diff --git a/src/Avalonia.Styling/Properties/AssemblyInfo.cs b/src/Avalonia.Styling/Properties/AssemblyInfo.cs index b53681aeed..0a639139f7 100644 --- a/src/Avalonia.Styling/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Styling/Properties/AssemblyInfo.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using Avalonia.Metadata; [assembly: AssemblyTitle("Avalonia.Styling")] +[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] +[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.LogicalTree")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Styling")] [assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests")] \ No newline at end of file diff --git a/src/Avalonia.Styling/Styling/Style.cs b/src/Avalonia.Styling/Styling/Style.cs index a0d4c8c087..6e79ee038e 100644 --- a/src/Avalonia.Styling/Styling/Style.cs +++ b/src/Avalonia.Styling/Styling/Style.cs @@ -18,7 +18,7 @@ namespace Avalonia.Styling private static Dictionary> _applied = new Dictionary>(); private IResourceNode _parent; - private ResourceDictionary _resources; + private IResourceDictionary _resources; /// /// Initializes a new instance of the class. @@ -44,15 +44,26 @@ namespace Avalonia.Styling /// public IResourceDictionary Resources { - get + get => _resources ?? (Resources = new ResourceDictionary()); + set { - if (_resources == null) + Contract.Requires(value != null); + + var hadResources = false; + + if (_resources != null) { - _resources = new ResourceDictionary(); - _resources.CollectionChanged += ResourceDictionaryChanged; + hadResources = _resources.Count > 0; + _resources.ResourcesChanged -= ResourceDictionaryChanged; } - return _resources; + _resources = value; + _resources.ResourcesChanged += ResourceDictionaryChanged; + + if (hadResources || _resources.Count > 0) + { + ((ISetStyleParent)this).NotifyResourcesChanged(new ResourcesChangedEventArgs()); + } } } @@ -180,9 +191,9 @@ namespace Avalonia.Styling _applied.Remove(control); } - private void ResourceDictionaryChanged(object sender, NotifyCollectionChangedEventArgs e) + private void ResourceDictionaryChanged(object sender, ResourcesChangedEventArgs e) { - ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs()); + ResourcesChanged?.Invoke(this, e); } } } diff --git a/src/Avalonia.Styling/Styling/Styles.cs b/src/Avalonia.Styling/Styling/Styles.cs index 767d5ce463..714e7f6def 100644 --- a/src/Avalonia.Styling/Styling/Styles.cs +++ b/src/Avalonia.Styling/Styling/Styles.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Collections.Specialized; using System.Linq; using Avalonia.Collections; using Avalonia.Controls; @@ -15,7 +14,7 @@ namespace Avalonia.Styling public class Styles : AvaloniaList, IStyle, ISetStyleParent { private IResourceNode _parent; - private ResourceDictionary _resources; + private IResourceDictionary _resources; public Styles() { @@ -65,15 +64,26 @@ namespace Avalonia.Styling /// public IResourceDictionary Resources { - get + get => _resources ?? (Resources = new ResourceDictionary()); + set { - if (_resources == null) + Contract.Requires(value != null); + + var hadResources = false; + + if (_resources != null) { - _resources = new ResourceDictionary(); - _resources.CollectionChanged += ResourceDictionaryChanged; + hadResources = _resources.Count > 0; + _resources.ResourcesChanged -= ResourceDictionaryChanged; } - return _resources; + _resources = value; + _resources.ResourcesChanged += ResourceDictionaryChanged; + + if (hadResources || _resources.Count > 0) + { + ((ISetStyleParent)this).NotifyResourcesChanged(new ResourcesChangedEventArgs()); + } } } @@ -132,16 +142,14 @@ namespace Avalonia.Styling ResourcesChanged?.Invoke(this, e); } - private void ResourceDictionaryChanged(object sender, NotifyCollectionChangedEventArgs e) + private void ResourceDictionaryChanged(object sender, ResourcesChangedEventArgs e) { - var ev = new ResourcesChangedEventArgs(); - foreach (var child in this) { - (child as ISetStyleParent)?.NotifyResourcesChanged(ev); + (child as ISetStyleParent)?.NotifyResourcesChanged(e); } - ResourcesChanged?.Invoke(this, ev); + ResourcesChanged?.Invoke(this, e); } private void SubResourceChanged(object sender, ResourcesChangedEventArgs e) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs index ed3ab3cc52..862ce2b3c0 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs @@ -104,6 +104,64 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions } } + [Fact] + public void StaticResource_From_MergedDictionary_Can_Be_Assigned_To_Property() + { + var xaml = @" + + + + + + #ff506070 + + + + + + +"; + + var loader = new AvaloniaXamlLoader(); + var userControl = (UserControl)loader.Load(xaml); + var border = userControl.FindControl("border"); + + var brush = (SolidColorBrush)border.Background; + Assert.Equal(0xff506070, brush.Color.ToUint32()); + } + + [Fact] + public void StaticResource_From_MergedDictionary_In_Style_Can_Be_Assigned_To_Property() + { + var xaml = @" + + + + + + +"; + + var loader = new AvaloniaXamlLoader(); + var userControl = (UserControl)loader.Load(xaml); + var border = userControl.FindControl("border"); + + var brush = (SolidColorBrush)border.Background; + Assert.Equal(0xff506070, brush.Color.ToUint32()); + } + [Fact] public void StaticResource_From_Application_Can_Be_Assigned_To_Property_In_UserControl() {