diff --git a/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs b/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs index 1b3a43a60..157b43f11 100644 --- a/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs +++ b/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; using System.Collections.Generic; using Xamarin.Forms.Internals; +using System.Collections.ObjectModel; namespace Xamarin.Forms.Core.UnitTests { @@ -410,5 +411,61 @@ namespace Xamarin.Forms.Core.UnitTests Assert.That(rd.MergedDictionaries.Count, Is.EqualTo(0)); } + + [Test] + public void AddingMergedRDTriggersValueChanged() + { + var rd = new ResourceDictionary(); + var label = new Label { + Resources = rd + }; + label.SetDynamicResource(Label.TextProperty, "foo"); + Assert.That(label.Text, Is.EqualTo(Label.TextProperty.DefaultValue)); + + rd.MergedDictionaries.Add(new ResourceDictionary { { "foo", "Foo"} }); + Assert.That(label.Text, Is.EqualTo("Foo")); + } + + [Test] + //this is to keep the alignment with resources removed from RD + public void RemovingMergedRDDoesntTriggersValueChanged() + { + var rd = new ResourceDictionary { + MergedDictionaries = { + new ResourceDictionary { + { "foo", "Foo" } + } + } + }; + var label = new Label { + Resources = rd, + }; + + label.SetDynamicResource(Label.TextProperty, "foo"); + Assert.That(label.Text, Is.EqualTo("Foo")); + + rd.MergedDictionaries.Clear(); + Assert.That(label.Text, Is.EqualTo("Foo")); + } + + [Test] + public void AddingResourceInMergedRDTriggersValueChanged() + { + var rd0 = new ResourceDictionary (); + var rd = new ResourceDictionary { + MergedDictionaries = { + rd0 + } + }; + + var label = new Label { + Resources = rd, + }; + label.SetDynamicResource(Label.TextProperty, "foo"); + Assert.That(label.Text, Is.EqualTo(Label.TextProperty.DefaultValue)); + + rd0.Add("foo", "Foo"); + Assert.That(label.Text, Is.EqualTo("Foo")); + } } } \ No newline at end of file diff --git a/Xamarin.Forms.Core/ResourceDictionary.cs b/Xamarin.Forms.Core/ResourceDictionary.cs index c9d59f83e..b3cb32146 100644 --- a/Xamarin.Forms.Core/ResourceDictionary.cs +++ b/Xamarin.Forms.Core/ResourceDictionary.cs @@ -14,8 +14,9 @@ namespace Xamarin.Forms { static ConditionalWeakTable s_instances = new ConditionalWeakTable(); readonly Dictionary _innerDictionary = new Dictionary(); - + ResourceDictionary _mergedInstance; Type _mergedWith; + [TypeConverter (typeof(TypeTypeConverter))] public Type MergedWith { get { return _mergedWith; } @@ -35,57 +36,60 @@ namespace Xamarin.Forms } } - ResourceDictionary _mergedInstance; - public ICollection MergedDictionaries { get; private set; } - - public ResourceDictionary() - { - var collection = new ObservableCollection(); - collection.CollectionChanged += MergedDictionaries_CollectionChanged; - MergedDictionaries = collection; + ICollection _mergedDictionaries; + public ICollection MergedDictionaries { + get { + if (_mergedDictionaries == null) { + var col = new ObservableCollection(); + col.CollectionChanged += MergedDictionaries_CollectionChanged; + _mergedDictionaries = col; + } + return _mergedDictionaries; + } } + IList _collectionTrack; + void MergedDictionaries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - // Movement of items doesn't affect monitoring of events + // Move() isn't exposed by ICollection if (e.Action == NotifyCollectionChangedAction.Move) return; - // New Items - var newItems = e.NewItems?.Cast(); - if (newItems != null) - { - foreach (var item in newItems) - { - _collectionTrack.Add(item); - item.ValuesChanged += Item_ValuesChanged; - } - - if (newItems.Count() > 0) - OnValuesChanged(newItems.SelectMany(x => x).ToArray()); - } - - // Old Items - var oldItems = e.OldItems?.Cast(); - if (oldItems != null) - foreach (var item in oldItems) - { - item.ValuesChanged -= Item_ValuesChanged; - _collectionTrack.Remove(item); - } - + _collectionTrack = _collectionTrack ?? new List(); // Collection has been cleared - if (e.Action == NotifyCollectionChangedAction.Reset) - { + if (e.Action == NotifyCollectionChangedAction.Reset) { foreach (var dictionary in _collectionTrack) dictionary.ValuesChanged -= Item_ValuesChanged; _collectionTrack.Clear(); + return; + } + + // New Items + if (e.NewItems != null) + { + foreach (var item in e.NewItems) + { + var rd = (ResourceDictionary)item; + _collectionTrack.Add(rd); + rd.ValuesChanged += Item_ValuesChanged; + OnValuesChanged(rd.ToArray()); + } + } + + // Old Items + if (e.OldItems != null) + { + foreach (var item in e.OldItems) + { + var rd = (ResourceDictionary)item; + rd.ValuesChanged -= Item_ValuesChanged; + _collectionTrack.Remove(rd); + } } } - IList _collectionTrack = new List(); - void Item_ValuesChanged(object sender, ResourcesChangedEventArgs e) { OnValuesChanged(e.Values.ToArray());