This commit is contained in:
Adam Pedley 2017-05-15 14:01:53 +10:00 коммит произвёл Stephane Delcroix
Родитель ec638b8604
Коммит 2b7913adda
4 изменённых файлов: 163 добавлений и 8 удалений

Просмотреть файл

@ -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&lt;Xamarin.Forms.ResourceDictionary&gt; MergedDictionaries { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.ICollection`1&lt;class Xamarin.Forms.ResourceDictionary&gt; MergedDictionaries" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Collections.Generic.ICollection&lt;Xamarin.Forms.ResourceDictionary&gt;</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" />