File: FillResourceDictionariesVisitor.cs
Web Access
Project: src\src\Controls\src\Xaml\Controls.Xaml.csproj (Microsoft.Maui.Controls.Xaml)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Controls.Xaml.Internals;
 
namespace Microsoft.Maui.Controls.Xaml
{
	[RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)]
#if !NETSTANDARD
	[RequiresDynamicCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)]
#endif
	class FillResourceDictionariesVisitor : IXamlNodeVisitor
	{
		public FillResourceDictionariesVisitor(HydrationContext context) => Context = context;
 
		HydrationContext Context { get; }
		Dictionary<INode, object> Values => Context.Values;
 
		public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
		public bool StopOnDataTemplate => true;
		public bool StopOnResourceDictionary => false;
		public bool VisitNodeOnDataTemplate => false;
 
		public bool IsResourceDictionary(ElementNode node) => typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]);
 
		public void Visit(ValueNode node, INode parentNode)
		{
			if (!Context.Types.TryGetValue((IElementNode)parentNode, out var type) || !typeof(ResourceDictionary).IsAssignableFrom(type))
				return;
 
			node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
		}
 
		public void Visit(MarkupNode node, INode parentNode)
		{
		}
 
		public void Visit(ElementNode node, INode parentNode)
		{
			if (!Values.TryGetValue(node, out var value) && Context.ExceptionHandler != null)
				return;
 
			//Set RD to VE
			if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]) && node.TryGetPropertyName(parentNode, out XmlName propertyName))
			{
				if ((propertyName.LocalName == "Resources" ||
					 propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary)
				{
					var source = Values[parentNode];
					ApplyPropertiesVisitor.SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
					return;
				}
			}
 
			//Only proceed further if the node is a keyless RD
			if (parentNode is IElementNode
				&& Context.Types.TryGetValue((IElementNode)parentNode, out var parentType)
				&& typeof(ResourceDictionary).IsAssignableFrom(parentType)
				&& !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey))
				node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
			else if (parentNode is ListNode
					 && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode.Parent)])
					 && !((IElementNode)parentNode.Parent).Properties.ContainsKey(XmlName.xKey))
				node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
		}
 
		public void Visit(RootNode node, INode parentNode)
		{
		}
 
		public void Visit(ListNode node, INode parentNode)
		{
		}
 
		public bool SkipChildren(INode node, INode parentNode)
		{
			if (!(node is ElementNode))
				return false;
			if (parentNode is IElementNode
				&& Context.Types.TryGetValue((IElementNode)parentNode, out var parentType)
				&& typeof(ResourceDictionary).IsAssignableFrom(parentType)
				&& !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey))
				return true;
			if (parentNode is ListNode
				&& typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode.Parent)])
				&& !((IElementNode)parentNode.Parent).Properties.ContainsKey(XmlName.xKey))
				return true;
			return false;
		}
 
	}
}