Merged Dictionaries
This commit is contained in:
Родитель
ec638b8604
Коммит
2b7913adda
|
@ -348,7 +348,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
[Test]
|
||||
public void TryGetValueLookupInMerged()
|
||||
{
|
||||
var rd = new ResourceDictionary {
|
||||
var rd = new ResourceDictionary {
|
||||
{"baz", "BAZ"},
|
||||
{"qux", "QUX"},
|
||||
};
|
||||
|
@ -357,6 +357,58 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
object _;
|
||||
Assert.That(rd.TryGetValue("foo", out _), Is.True);
|
||||
Assert.That(rd.TryGetValue("baz", out _), Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergedDictionaryResourcesAreFound()
|
||||
{
|
||||
var rd0 = new ResourceDictionary();
|
||||
rd0.MergedDictionaries.Add(new ResourceDictionary() { { "foo", "bar" } });
|
||||
|
||||
object value;
|
||||
Assert.True(rd0.TryGetValue("foo", out value));
|
||||
Assert.AreEqual("bar", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MergedDictionaryResourcesAreFoundLastDictionaryTakesPriority()
|
||||
{
|
||||
var rd0 = new ResourceDictionary();
|
||||
rd0.MergedDictionaries.Add(new ResourceDictionary() { { "foo", "bar" } });
|
||||
rd0.MergedDictionaries.Add(new ResourceDictionary() { { "foo", "bar1" } });
|
||||
rd0.MergedDictionaries.Add(new ResourceDictionary() { { "foo", "bar2" } });
|
||||
|
||||
object value;
|
||||
Assert.True(rd0.TryGetValue("foo", out value));
|
||||
Assert.AreEqual("bar2", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CountDoesNotIncludeMergedDictionaries()
|
||||
{
|
||||
var rd = new ResourceDictionary {
|
||||
{"baz", "Baz"},
|
||||
{"qux", "Qux"},
|
||||
};
|
||||
rd.MergedDictionaries.Add(new ResourceDictionary() { { "foo", "bar" } });
|
||||
|
||||
Assert.That(rd.Count, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClearMergedDictionaries()
|
||||
{
|
||||
var rd = new ResourceDictionary {
|
||||
{"baz", "Baz"},
|
||||
{"qux", "Qux"},
|
||||
};
|
||||
rd.MergedDictionaries.Add(new ResourceDictionary() { { "foo", "bar" } });
|
||||
|
||||
Assert.That(rd.Count, Is.EqualTo(2));
|
||||
|
||||
rd.MergedDictionaries.Clear();
|
||||
|
||||
Assert.That(rd.MergedDictionaries.Count, Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<ResourceDictionary> MergedDictionaries { get; private set; }
|
||||
|
||||
public ResourceDictionary()
|
||||
{
|
||||
var collection = new ObservableCollection<ResourceDictionary>();
|
||||
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<ResourceDictionary>();
|
||||
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<ResourceDictionary>();
|
||||
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<ResourceDictionary> _collectionTrack = new List<ResourceDictionary>();
|
||||
|
||||
void Item_ValuesChanged(object sender, ResourcesChangedEventArgs e)
|
||||
{
|
||||
OnValuesChanged(e.Values.ToArray());
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> 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<KeyValuePair<string, object>> 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<ResourcesChangedEventArgs> IResourceDictionary.ValuesChanged
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.Xaml.Internals;
|
||||
|
||||
|
@ -106,12 +105,25 @@ namespace Xamarin.Forms.Xaml
|
|||
if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName))
|
||||
{
|
||||
if ((propertyName.LocalName == "Resources" ||
|
||||
propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary)
|
||||
propertyName.LocalName == "MergedDictionaries" ||
|
||||
propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary)
|
||||
{
|
||||
var source = Values[parentNode];
|
||||
ApplyPropertiesVisitor.SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
|
||||
}
|
||||
}
|
||||
|
||||
//Add ResourceDictionary into MergedDictionaries
|
||||
XmlName parentPropertyName;
|
||||
if (parentNode is IListNode && ApplyPropertiesVisitor.TryGetPropertyName(parentNode, parentNode.Parent, out parentPropertyName))
|
||||
{
|
||||
if (parentPropertyName.LocalName == "MergedDictionaries")
|
||||
{
|
||||
var source = Values[parentNode.Parent];
|
||||
node.Parent = node.Parent.Parent;
|
||||
ApplyPropertiesVisitor.SetPropertyValue(source, parentPropertyName, value, Context.RootElement, node, Context, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Visit(RootNode node, INode parentNode)
|
||||
|
|
|
@ -246,6 +246,22 @@
|
|||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="MergedDictionaries">
|
||||
<MemberSignature Language="C#" Value="public System.Collections.Generic.ICollection<Xamarin.Forms.ResourceDictionary> MergedDictionaries { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.ICollection`1<class Xamarin.Forms.ResourceDictionary> MergedDictionaries" />
|
||||
<MemberType>Property</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>System.Collections.Generic.ICollection<Xamarin.Forms.ResourceDictionary></ReturnType>
|
||||
</ReturnValue>
|
||||
<Docs>
|
||||
<summary>To be added.</summary>
|
||||
<value>To be added.</value>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="MergedWith">
|
||||
<MemberSignature Language="C#" Value="public Type MergedWith { get; set; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance class System.Type MergedWith" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче