From b3a790fb0a7182c9bfe7a18196f8a10916903faf Mon Sep 17 00:00:00 2001 From: Adam Pedley Date: Mon, 15 May 2017 14:01:53 +1000 Subject: Merged Dictionaries --- Xamarin.Forms.Core/ResourceDictionary.cs | 83 ++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 4 deletions(-) (limited to 'Xamarin.Forms.Core') diff --git a/Xamarin.Forms.Core/ResourceDictionary.cs b/Xamarin.Forms.Core/ResourceDictionary.cs index 2fc11ffc..c9d59f83 100644 --- a/Xamarin.Forms.Core/ResourceDictionary.cs +++ b/Xamarin.Forms.Core/ResourceDictionary.cs @@ -5,6 +5,8 @@ using System.Runtime.CompilerServices; using System.Linq; using System.Reflection; using Xamarin.Forms.Internals; +using System.Collections.ObjectModel; +using System.Collections.Specialized; namespace Xamarin.Forms { @@ -17,7 +19,7 @@ namespace Xamarin.Forms [TypeConverter (typeof(TypeTypeConverter))] public Type MergedWith { get { return _mergedWith; } - set { + set { if (_mergedWith == value) return; @@ -28,12 +30,66 @@ namespace Xamarin.Forms if (_mergedWith == null) return; - _mergedInstance = s_instances.GetValue(_mergedWith,(key) => (ResourceDictionary)Activator.CreateInstance(key)); - OnValuesChanged (_mergedInstance.ToArray()); + _mergedInstance = s_instances.GetValue(_mergedWith, (key) => (ResourceDictionary)Activator.CreateInstance(key)); + OnValuesChanged(_mergedInstance.ToArray()); } } ResourceDictionary _mergedInstance; + public ICollection MergedDictionaries { get; private set; } + + public ResourceDictionary() + { + var collection = new ObservableCollection(); + collection.CollectionChanged += MergedDictionaries_CollectionChanged; + MergedDictionaries = collection; + } + + void MergedDictionaries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + // Movement of items doesn't affect monitoring of events + 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); + } + + // Collection has been cleared + if (e.Action == NotifyCollectionChangedAction.Reset) + { + foreach (var dictionary in _collectionTrack) + dictionary.ValuesChanged -= Item_ValuesChanged; + + _collectionTrack.Clear(); + } + } + + IList _collectionTrack = new List(); + + void Item_ValuesChanged(object sender, ResourcesChangedEventArgs e) + { + OnValuesChanged(e.Values.ToArray()); + } void ICollection>.Add(KeyValuePair item) { @@ -94,6 +150,10 @@ namespace Xamarin.Forms return _innerDictionary[index]; if (_mergedInstance != null && _mergedInstance.ContainsKey(index)) return _mergedInstance[index]; + if (MergedDictionaries != null) + foreach (var dict in MergedDictionaries.Reverse()) + if (dict.ContainsKey(index)) + return dict[index]; throw new KeyNotFoundException($"The resource '{index}' is not present in the dictionary."); } set @@ -130,6 +190,9 @@ namespace Xamarin.Forms internal IEnumerable> MergedResources { get { + if (MergedDictionaries != null) + foreach (var r in MergedDictionaries.Reverse().SelectMany(x => x.MergedResources)) + yield return r; if (_mergedInstance != null) foreach (var r in _mergedInstance.MergedResources) yield return r; @@ -140,7 +203,19 @@ namespace Xamarin.Forms public bool TryGetValue(string key, out object value) { - return _innerDictionary.TryGetValue(key, out value) || (_mergedInstance != null && _mergedInstance.TryGetValue(key, out value)); + return _innerDictionary.TryGetValue(key, out value) + || (_mergedInstance != null && _mergedInstance.TryGetValue(key, out value)) + || (MergedDictionaries != null && TryGetMergedDictionaryValue(key, out value)); + } + + bool TryGetMergedDictionaryValue(string key, out object value) + { + foreach (var dictionary in MergedDictionaries.Reverse()) + if (dictionary.TryGetValue(key, out value)) + return true; + + value = null; + return false; } event EventHandler IResourceDictionary.ValuesChanged -- cgit v1.2.3