summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Xaml
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-08-16 20:33:44 +0200
committerJason Smith <jason.smith@xamarin.com>2016-08-16 11:33:44 -0700
commit4226f5b386a83dc9eb2f0c06f4920ac1be19e036 (patch)
treea1e0e9ac88967d31d52750e4082d29695079f4a8 /Xamarin.Forms.Xaml
parent3ca06ea14603abded9c15287865a51a3add4e436 (diff)
downloadxamarin-forms-4226f5b386a83dc9eb2f0c06f4920ac1be19e036.tar.gz
xamarin-forms-4226f5b386a83dc9eb2f0c06f4920ac1be19e036.tar.bz2
xamarin-forms-4226f5b386a83dc9eb2f0c06f4920ac1be19e036.zip
[Xaml] Clone node tree on DT, allow markup to be evaluated multiple times (#295)
Diffstat (limited to 'Xamarin.Forms.Xaml')
-rw-r--r--Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs16
-rw-r--r--Xamarin.Forms.Xaml/XamlNode.cs42
2 files changed, 51 insertions, 7 deletions
diff --git a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
index 108d707e..327a4122 100644
--- a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
+++ b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
@@ -433,14 +433,16 @@ namespace Xamarin.Forms.Xaml
((IDataTemplate)dt).LoadTemplate = () =>
{
#pragma warning restore 0612
+ var cnode = node.Clone();
var context = new HydratationContext { ParentContext = Context, RootElement = Context.RootElement };
- node.Accept(new ExpandMarkupsVisitor(context), null);
- node.Accept(new NamescopingVisitor(context), null);
- node.Accept(new CreateValuesVisitor(context), null);
- node.Accept(new RegisterXNamesVisitor(context), null);
- node.Accept(new FillResourceDictionariesVisitor(context), null);
- node.Accept(new ApplyPropertiesVisitor(context, true), null);
- return context.Values[node];
+ cnode.Accept(new XamlNodeVisitor((n, parent) => n.Parent = parent), node.Parent); //set parents for {StaticResource}
+ cnode.Accept(new ExpandMarkupsVisitor(context), null);
+ cnode.Accept(new NamescopingVisitor(context), null);
+ cnode.Accept(new CreateValuesVisitor(context), null);
+ cnode.Accept(new RegisterXNamesVisitor(context), null);
+ cnode.Accept(new FillResourceDictionariesVisitor(context), null);
+ cnode.Accept(new ApplyPropertiesVisitor(context, true), null);
+ return context.Values[cnode];
};
}
}
diff --git a/Xamarin.Forms.Xaml/XamlNode.cs b/Xamarin.Forms.Xaml/XamlNode.cs
index 6d84c67d..f794428b 100644
--- a/Xamarin.Forms.Xaml/XamlNode.cs
+++ b/Xamarin.Forms.Xaml/XamlNode.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -15,6 +16,7 @@ namespace Xamarin.Forms.Xaml
INode Parent { get; set; }
void Accept(IXamlNodeVisitor visitor, INode parentNode);
+ INode Clone();
}
internal interface IValueNode : INode
@@ -81,6 +83,8 @@ namespace Xamarin.Forms.Xaml
public int LineNumber { get; set; }
public int LinePosition { get; set; }
+
+ public abstract INode Clone();
}
[DebuggerDisplay("{Value}")]
@@ -98,6 +102,13 @@ namespace Xamarin.Forms.Xaml
{
visitor.Visit(this, parentNode);
}
+
+ public override INode Clone()
+ {
+ return new ValueNode(Value, NamespaceResolver, LineNumber, LinePosition) {
+ IgnorablePrefixes = IgnorablePrefixes
+ };
+ }
}
[DebuggerDisplay("{MarkupString}")]
@@ -116,6 +127,13 @@ namespace Xamarin.Forms.Xaml
{
visitor.Visit(this, parentNode);
}
+
+ public override INode Clone()
+ {
+ return new MarkupNode(MarkupString, NamespaceResolver, LineNumber, LinePosition) {
+ IgnorablePrefixes = IgnorablePrefixes
+ };
+ }
}
internal class ElementNode : BaseNode, IValueNode, IElementNode
@@ -174,6 +192,20 @@ namespace Xamarin.Forms.Xaml
var enode = node as ElementNode;
return enode.XmlType.Name == "ResourceDictionary";
}
+
+ public override INode Clone()
+ {
+ var clone = new ElementNode(XmlType, NamespaceURI, NamespaceResolver, LineNumber, LinePosition) {
+ IgnorablePrefixes = IgnorablePrefixes
+ };
+ foreach (var kvp in Properties)
+ clone.Properties.Add(kvp.Key, kvp.Value.Clone());
+ foreach (var p in SkipProperties)
+ clone.SkipProperties.Add(p);
+ foreach (var p in CollectionItems)
+ clone.CollectionItems.Add(p.Clone());
+ return clone;
+ }
}
internal abstract class RootNode : ElementNode
@@ -220,6 +252,16 @@ namespace Xamarin.Forms.Xaml
if (visitor.VisitChildrenFirst)
visitor.Visit(this, parentNode);
}
+
+ public override INode Clone()
+ {
+ var items = new List<INode>();
+ foreach (var p in CollectionItems)
+ items.Add(p.Clone());
+ return new ListNode(items, NamespaceResolver, LineNumber, LinePosition) {
+ IgnorablePrefixes = IgnorablePrefixes
+ };
+ }
}
internal static class INodeExtensions