Forráskód Böngészése

Start testing MergedDictionaries.

Steven Kirk 8 éve
szülő
commit
91387a74e1

+ 25 - 2
src/Avalonia.Controls/Application.cs

@@ -39,7 +39,7 @@ namespace Avalonia
         private readonly Lazy<IClipboard> _clipboard =
             new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
         private readonly Styler _styler = new Styler();
-        private ResourceDictionary _resources;
+        private IResourceDictionary _resources;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="Application"/> class.
@@ -107,7 +107,30 @@ namespace Avalonia
         /// <summary>
         /// Gets the application's global resource dictionary.
         /// </summary>
-        public IResourceDictionary Resources => _resources ?? (_resources = new ResourceDictionary());
+        public IResourceDictionary Resources
+        {
+            get => _resources ?? (Resources = new ResourceDictionary());
+            set
+            {
+                Contract.Requires<ArgumentNullException>(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());
+                }
+            }
+        }
 
         /// <summary>
         /// Gets the application's global styles.

+ 17 - 6
src/Avalonia.Controls/Control.cs

@@ -97,7 +97,7 @@ namespace Avalonia.Controls
         private bool _isAttachedToLogicalTree;
         private IAvaloniaList<ILogical> _logicalChildren;
         private INameScope _nameScope;
-        private ResourceDictionary _resources;
+        private IResourceDictionary _resources;
         private Styles _styles;
         private bool _styled;
         private Subject<IStyleable> _styleDetach = new Subject<IStyleable>();
@@ -318,15 +318,26 @@ namespace Avalonia.Controls
         /// </summary>
         public IResourceDictionary Resources
         {
-            get
+            get => _resources ?? (Resources = new ResourceDictionary());
+            set
             {
-                if (_resources == null)
+                Contract.Requires<ArgumentNullException>(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());
+                }
             }
         }
 

+ 2 - 0
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")]

+ 19 - 8
src/Avalonia.Styling/Styling/Style.cs

@@ -18,7 +18,7 @@ namespace Avalonia.Styling
         private static Dictionary<IStyleable, List<IDisposable>> _applied =
             new Dictionary<IStyleable, List<IDisposable>>();
         private IResourceNode _parent;
-        private ResourceDictionary _resources;
+        private IResourceDictionary _resources;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="Style"/> class.
@@ -44,15 +44,26 @@ namespace Avalonia.Styling
         /// </summary>
         public IResourceDictionary Resources
         {
-            get
+            get => _resources ?? (Resources = new ResourceDictionary());
+            set
             {
-                if (_resources == null)
+                Contract.Requires<ArgumentNullException>(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);
         }
     }
 }

+ 20 - 12
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>, IStyle, ISetStyleParent
     {
         private IResourceNode _parent;
-        private ResourceDictionary _resources;
+        private IResourceDictionary _resources;
 
         public Styles()
         {
@@ -65,15 +64,26 @@ namespace Avalonia.Styling
         /// </summary>
         public IResourceDictionary Resources
         {
-            get
+            get => _resources ?? (Resources = new ResourceDictionary());
+            set
             {
-                if (_resources == null)
+                Contract.Requires<ArgumentNullException>(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)

+ 58 - 0
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 = @"
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary>
+                    <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
+                </ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </UserControl.Resources>
+
+    <Border Name='border' Background='{StaticResource brush}'/>
+</UserControl>";
+
+            var loader = new AvaloniaXamlLoader();
+            var userControl = (UserControl)loader.Load(xaml);
+            var border = userControl.FindControl<Border>("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 = @"
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
+    <UserControl.Styles>
+        <Style>
+            <Style.Resources>
+                <ResourceDictionary>
+                    <ResourceDictionary.MergedDictionaries>
+                        <ResourceDictionary>
+                            <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
+                        </ResourceDictionary>
+                    </ResourceDictionary.MergedDictionaries>
+                </ResourceDictionary>
+            </Style.Resources>
+        </Style>
+    </UserControl.Styles>
+
+    <Border Name='border' Background='{StaticResource brush}'/>
+</UserControl>";
+
+            var loader = new AvaloniaXamlLoader();
+            var userControl = (UserControl)loader.Load(xaml);
+            var border = userControl.FindControl<Border>("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()
         {