diff options
author | Stephane Delcroix <stephane@delcroix.org> | 2016-08-16 20:33:44 +0200 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-08-16 11:33:44 -0700 |
commit | 4226f5b386a83dc9eb2f0c06f4920ac1be19e036 (patch) | |
tree | a1e0e9ac88967d31d52750e4082d29695079f4a8 /Xamarin.Forms.Xaml | |
parent | 3ca06ea14603abded9c15287865a51a3add4e436 (diff) | |
download | xamarin-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.cs | 16 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml/XamlNode.cs | 42 |
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 |