File: System\Windows\FrameworkElementFactory.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Threading;
using System.Windows.Baml2006;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using System.Collections;               // For ArrayList
using System.Collections.Specialized;   // HybridDictionary
using System.Globalization;
using System.Windows.Media.Media3D;
using MS.Utility;
using MS.Internal;
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows
{
    /// <summary>
    ///     Templating instance representation
    /// </summary>
    [Localizability(LocalizationCategory.NeverLocalize)]
    public class FrameworkElementFactory
    {
        /// <summary>
        ///     Construction
        /// </summary>
        public FrameworkElementFactory() : this(null, null)
        {
            // Forwarding
        }
 
        /// <summary>
        ///     Construction
        /// </summary>
        /// <param name="type">Type of instance to create</param>
        public FrameworkElementFactory(Type type) : this(type, null)
        {
            // Forwarding
        }
 
        /// <summary>
        ///     Construction
        /// </summary>
        /// <param name="text">Text to add</param>
        public FrameworkElementFactory(string text) : this(null, null)
        {
            Text = text;
        }
 
        /// <summary>
        ///     Construction
        /// </summary>
        /// <param name="type">Type of instance to create</param>
        /// <param name="name">Style identifier</param>
        public FrameworkElementFactory(Type type, string name)
        {
            Type = type;
            Name = name;
        }
 
 
        /// <summary>
        ///     Type of object that the factory will produce
        /// </summary>
        public Type Type
        {
            get { return _type; }
            set
            {
                if (_sealed)
                {
                    throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
                }
 
                if (_text != null)
                {
                    throw new InvalidOperationException(SR.FrameworkElementFactoryCannotAddText);
                }
 
                if ( value != null ) // We allow null up until Seal
                {
                    // If non-null, must be derived from one of the supported types
                    if (!typeof(FrameworkElement).IsAssignableFrom(value) &&
                        !typeof(FrameworkContentElement).IsAssignableFrom(value) &&
                        !typeof(Visual3D).IsAssignableFrom(value))
                    {
                        #pragma warning suppress 6506 // value is obviously not null
                        throw new ArgumentException(SR.Format(SR.MustBeFrameworkOr3DDerived, value.Name));
                    }
                }
 
                // It is possible that _type is null when a FEF is created for text content within a tag
                _type = value;
 
                // If this is a KnownType in the BamlSchemaContext, then there is a faster way to create
                // an instance of that type than using Activator.CreateInstance.  So in that case
                // save the delegate for later creation.
                WpfKnownType knownType = null;
                if (_type != null)
                {
                    knownType = XamlReader.BamlSharedSchemaContext.GetKnownXamlType(_type) as WpfKnownType;
                }
                _knownTypeFactory = (knownType != null) ? knownType.DefaultConstructor : null;
            }
        }
 
        /// <summary>
        ///     Text string that the factory will produce
        /// </summary>
        public string Text
        {
            get { return _text; }
            set
            {
                if (_sealed)
                {
                    throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
                }
 
                if (_firstChild != null)
                {
                    throw new InvalidOperationException(SR.FrameworkElementFactoryCannotAddText);
                }
 
                ArgumentNullException.ThrowIfNull(value);
 
                _text = value;
            }
        }
 
        /// <summary>
        ///     Style identifier
        /// </summary>
        public string Name
        {
            get { return _childName; }
            set
            {
                if (_sealed)
                {
                    throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
                }
                if (value == string.Empty)
                {
                    throw new ArgumentException(SR.NameNotEmptyString);
                }
 
                _childName = value;
            }
        }
 
 
        /// <summary>
        ///     Add a factory child to this factory
        /// </summary>
        /// <param name="child">Child to add</param>
        public void AppendChild(FrameworkElementFactory child)
        {
            if (_sealed)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
            }
 
            ArgumentNullException.ThrowIfNull(child);
 
            if (child._parent != null)
            {
                throw new ArgumentException(SR.FrameworkElementFactoryAlreadyParented);
            }
 
            if (_text != null)
            {
                throw new InvalidOperationException(SR.FrameworkElementFactoryCannotAddText);
            }
 
            // Build tree of factories
            if (_firstChild == null)
            {
                _firstChild = child;
                _lastChild = child;
            }
            else
            {
                _lastChild._nextSibling = child;
                _lastChild = child;
            }
 
            child._parent = this;
        }
 
        /// <summary>
        ///     Simple value set on template child
        /// </summary>
        /// <param name="dp">Dependent property</param>
        /// <param name="value">Value to set</param>
        public void SetValue(DependencyProperty dp, object value)
        {
            if (_sealed)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
            }
 
            ArgumentNullException.ThrowIfNull(dp);
 
            // Value needs to be valid for the DP, or Binding/MultiBinding/PriorityBinding.
            //  (They all have MarkupExtension, which we don't actually support, see above check.)
 
            if (!dp.IsValidValue(value) && !(value is MarkupExtension) && !(value is DeferredReference))
            {
                throw new ArgumentException(SR.Format(SR.InvalidPropertyValue, value, dp.Name));
            }
 
            // Styling the logical tree is not supported
            if (StyleHelper.IsStylingLogicalTree(dp, value))
            {
                throw new NotSupportedException(SR.Format(SR.ModifyingLogicalTreeViaStylesNotImplemented, value, "FrameworkElementFactory.SetValue"));
            }
 
            #pragma warning suppress 6506 // dp.DefaultMetadata is never null
            if (dp.ReadOnly)
            {
                // Read-only properties will not be consulting FrameworkElementFactory for value.
                //  Rather than silently do nothing, throw error.
                throw new ArgumentException(SR.Format(SR.ReadOnlyPropertyNotAllowed, dp.Name, GetType().Name));
            }
 
            ResourceReferenceExpression resourceExpression = value as ResourceReferenceExpression;
            DynamicResourceExtension dynamicResourceExtension = value as DynamicResourceExtension;
            object resourceKey = null;
 
            if( resourceExpression != null )
            {
                resourceKey = resourceExpression.ResourceKey;
            }
            else if( dynamicResourceExtension != null )
            {
                resourceKey = dynamicResourceExtension.ResourceKey;
            }
 
            if (resourceKey == null)
            {
                TemplateBindingExtension templateBinding = value as TemplateBindingExtension;
                if (templateBinding == null)
                {
                    UpdatePropertyValueList( dp, PropertyValueType.Set, value );
                }
                else
                {
                    UpdatePropertyValueList( dp, PropertyValueType.TemplateBinding, templateBinding );
                }
            }
            else
            {
                UpdatePropertyValueList(dp, PropertyValueType.Resource, resourceKey);
            }
        }
 
        /// <summary>
        ///     Set up data binding on template child
        /// </summary>
        /// <param name="dp">Dependent property</param>
        /// <param name="binding">Description of binding</param>
        public void SetBinding(DependencyProperty dp, BindingBase binding)
        {
            // store Binding in the style - this will get converted to Binding
            // on demand (see Style.ProcessApplyValuesHelper)
            SetValue(dp, binding);
        }
 
        /// <summary>
        ///     Resource binding on template child
        /// </summary>
        /// <param name="dp">Dependent property</param>
        /// <param name="name">Resource identifier</param>
        public void SetResourceReference(DependencyProperty dp, object name)
        {
            if (_sealed)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
            }
 
            ArgumentNullException.ThrowIfNull(dp);
 
            UpdatePropertyValueList( dp, PropertyValueType.Resource, name );
        }
 
        /// <summary>
        ///     Add an event handler for the given routed event. This action applies to the instances created by this factory
        /// </summary>
        public void AddHandler(RoutedEvent routedEvent, Delegate handler)
        {
            // HandledEventToo defaults to false
            // Call forwarded
            AddHandler(routedEvent, handler, false);
        }
 
        /// <summary>
        ///     Add an event handler for the given routed event. This action applies to the instances created by this factory
        /// </summary>
        public void AddHandler(RoutedEvent routedEvent, Delegate handler, bool handledEventsToo)
        {
            if (_sealed)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
            }
 
            ArgumentNullException.ThrowIfNull(routedEvent);
            ArgumentNullException.ThrowIfNull(handler);
 
            if (handler.GetType() != routedEvent.HandlerType)
            {
                throw new ArgumentException(SR.HandlerTypeIllegal);
            }
 
            if (_eventHandlersStore == null)
            {
                _eventHandlersStore = new EventHandlersStore();
            }
 
            _eventHandlersStore.AddRoutedEventHandler(routedEvent, handler, handledEventsToo);
 
            // Keep track of whether we're listening to the loaded or unloaded events;
            // if so, we have to trigger a listener in the FE/FCE (as a performance
            // optimization).
 
            if (  (routedEvent == FrameworkElement.LoadedEvent)
                ||(routedEvent == FrameworkElement.UnloadedEvent))
            {
                HasLoadedChangeHandler = true;
            }
        }
 
        /// <summary>
        ///     Remove an event handler for the given routed event. This action applies to the instances created by this factory
        /// </summary>
        public void RemoveHandler(RoutedEvent routedEvent, Delegate handler)
        {
            if (_sealed)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
            }
 
            ArgumentNullException.ThrowIfNull(routedEvent);
            ArgumentNullException.ThrowIfNull(handler);
 
            if (handler.GetType() != routedEvent.HandlerType)
            {
                throw new ArgumentException(SR.HandlerTypeIllegal);
            }
 
            if (_eventHandlersStore != null)
            {
                _eventHandlersStore.RemoveRoutedEventHandler(routedEvent, handler);
 
                // Update the loaded/unloaded optimization flags if necessary
 
                if (  (routedEvent == FrameworkElement.LoadedEvent)
                    ||(routedEvent == FrameworkElement.UnloadedEvent))
                {
                    if (  !_eventHandlersStore.Contains(FrameworkElement.LoadedEvent)
                        &&!_eventHandlersStore.Contains(FrameworkElement.UnloadedEvent))
                    {
                        HasLoadedChangeHandler = false;
                    }
                }
            }
        }
 
        /// <summary>
        ///     Store all the event handlers for this FEF
        /// </summary>
        internal EventHandlersStore EventHandlersStore
        {
            get
            {
                return _eventHandlersStore;
            }
            set
            {
                _eventHandlersStore = value;
            }
        }
 
 
        //
        // Says if we have anything listening for the Loaded or Unloaded
        // event (used for an optimization in FrameworkElement).
        //
 
        internal bool HasLoadedChangeHandler
        {
            get { return _hasLoadedChangeHandler; }
            set { _hasLoadedChangeHandler = value; }
        }
 
 
 
        /// <summary>
        ///     Given a set of values for the PropertyValue struct, put that in
        /// to the PropertyValueList, overwriting any existing entry.
        /// </summary>
        private void UpdatePropertyValueList(
            DependencyProperty dp,
            PropertyValueType valueType,
            object value)
        {
            // Check for existing value on dp
            int existingIndex = -1;
            for( int i = 0; i < PropertyValues.Count; i++ )
            {
                if( PropertyValues[i].Property == dp )
                {
                    existingIndex = i;
                    break;
                }
            }
 
            if( existingIndex >= 0 )
            {
                // Overwrite existing value for dp
                lock (_synchronized)
                {
                    PropertyValue propertyValue = PropertyValues[existingIndex];
                    propertyValue.ValueType = valueType;
                    propertyValue.ValueInternal = value;
                    // Put back modified struct
                    PropertyValues[existingIndex] = propertyValue;
                }
            }
            else
            {
                // Store original data
                PropertyValue propertyValue = new PropertyValue();
                propertyValue.ValueType = valueType;
                propertyValue.ChildName = null;  // Delayed
                propertyValue.Property = dp;
                propertyValue.ValueInternal = value;
 
                lock (_synchronized)
                {
                    PropertyValues.Add(propertyValue);
                }
            }
        }
 
        /// <summary>
        ///     Create a DependencyObject instance of the specified type
        /// </summary>
        /// <remarks>
        ///     By default, reflection is used to create the instance. For
        ///     best perf, override this and do specific construction
        /// </remarks>
        /// <returns>New instance</returns>
        private DependencyObject CreateDependencyObject()
        {
            // Not expecting InvalidCastException - Type.set should have
            //  verified that it is a FrameworkElement or FrameworkContentElement.
 
            if (_knownTypeFactory != null)
            {
                return _knownTypeFactory.Invoke() as DependencyObject;
            }
 
            return (DependencyObject)Activator.CreateInstance(_type);
        }
 
        /// <summary>
        ///     FrameworkElementFactory mutability state
        /// </summary>
        public bool IsSealed
        {
            get { return _sealed; }
        }
 
 
        /// <summary>
        ///     Parent factory
        /// </summary>
        public FrameworkElementFactory Parent
        {
            get { return _parent; }
        }
 
        /// <summary>
        ///     First child factory
        /// </summary>
        public FrameworkElementFactory FirstChild
        {
            get { return _firstChild; }
        }
 
        /// <summary>
        ///     Next sibling factory
        /// </summary>
        public FrameworkElementFactory NextSibling
        {
            get { return _nextSibling; }
        }
 
        internal FrameworkTemplate FrameworkTemplate
        {
            get { return _frameworkTemplate; }
        }
 
 
        internal object GetValue(DependencyProperty dp)
        {
            // Retrieve a value previously set
 
            // Scan for record
            for (int i = 0; i < PropertyValues.Count; i++)
            {
                var propertyValue = PropertyValues[i];
                if (propertyValue.ValueType == PropertyValueType.Set &&
                    propertyValue.Property == dp)
                {
                    // Found a Set record, return the value
                    return propertyValue.ValueInternal;
                }
            }
 
            return DependencyProperty.UnsetValue;
        }
 
        // Seal this FEF
        internal void Seal(FrameworkTemplate ownerTemplate)
        {
            if (_sealed)
            {
                return;
            }
 
            // Store owner Template
            _frameworkTemplate = ownerTemplate;
 
            // Perform actual Seal operation
            Seal();
        }
 
        private void Seal()
        {
            if (_type == null && _text == null)
            {
                throw new InvalidOperationException(SR.NullTypeIllegal);
            }
 
            if (_firstChild != null)
            {
                // This factory has children, it must implement IAddChild so that these
                // children can be added to the logical tree
                if (!typeof(IAddChild).IsAssignableFrom(_type))
                {
                    throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild, _type.Name));
                }
            }
 
            ApplyAutoAliasRules();
 
            if ((_childName != null) && (_childName != String.Empty))
            {
                // ChildName provided
                if (!IsChildNameValid(_childName))
                {
                    throw new InvalidOperationException(SR.Format(SR.ChildNameNamePatternReserved, _childName));
                }
 
                _childName = String.Intern(_childName);
            }
            else
            {
                // ChildName not provided
 
                _childName = GenerateChildName();
            }
 
 
            lock (_synchronized)
            {
                // Set delayed ChildID for all property triggers
                for (int i = 0; i < PropertyValues.Count; i++)
                {
                    PropertyValue propertyValue = PropertyValues[i];
                    propertyValue.ChildName = _childName;
 
                    // Freeze the FEF property value
                    StyleHelper.SealIfSealable(propertyValue.ValueInternal);
 
                    // Put back modified struct
                    PropertyValues[i] = propertyValue;
                }
            }
 
 
            _sealed = true;
 
            // Convert ChildName to Template-specific ChildIndex, if applicable
            if ((_childName != null) && (_childName != String.Empty) &&
                _frameworkTemplate != null )
            {
                _childIndex = StyleHelper.CreateChildIndexFromChildName(_childName, _frameworkTemplate);
            }
 
            // Seal all children
            FrameworkElementFactory child = _firstChild;
            while (child != null)
            {
                if (_frameworkTemplate != null)
                {
                    child.Seal(_frameworkTemplate);
                }
 
                child = child._nextSibling;
            }
        }
 
        // Instantiate a tree.  This is a recursive routine that will build the
        //  subtree via calls to itself.  The root node being instantiated will
        //  have identical references for the "container" and "parent" parameters.
        // The "affectedChildren" and "noChildIndexChildren" parameters refer to the children
        //  chain for the "container" object.  This chain will have all the
        //  children - not just the immediate children.  The node being
        //  instantiated here will be added to this chain.
        // The tree is instantiated in a depth-first traversal, so children nodes
        //  are added to the chain in depth-first order as well.
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647
        internal DependencyObject InstantiateTree(
                UncommonField<HybridDictionary[]>           dataField,
                DependencyObject                            container,
                DependencyObject                            parent,
                List<DependencyObject>                      affectedChildren,
            ref List<DependencyObject>                      noChildIndexChildren,
            ref FrugalStructList<ChildPropertyDependent>    resourceDependents)
        {
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstBegin);
 
            FrameworkElement containerAsFE = container as FrameworkElement;
            bool isContainerAnFE = containerAsFE != null;
 
            DependencyObject treeNode = null;
            // If we have text, just add it to the parent.  Otherwise create the child
            // subtree
            if (_text != null)
            {
                // of FrameworkContentElement parent.  This is the logical equivalent
                // to what happens when adding a child to a visual collection.
                IAddChild addChildParent = parent as IAddChild;
 
                if (addChildParent == null)
                {
                    throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild,
                                                         parent.GetType().Name));
                }
                else
                {
                    addChildParent.AddText(_text);
                }
            }
            else
            {
                // Factory create instance
                treeNode = CreateDependencyObject();
 
                EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstEnd);
 
                // The tree node is either a FrameworkElement or a FrameworkContentElement.
                //  we'll deal with one or the other...
                FrameworkObject treeNodeFO = new FrameworkObject(treeNode);
 
                Visual3D treeNodeVisual3D = null;
                bool treeNodeIsVisual3D = false;
 
                if (!treeNodeFO.IsValid)
                {
                    // If it's neither of those, we have special support for Visual3D
 
                    treeNodeVisual3D = treeNode as Visual3D;
                    if (treeNodeVisual3D != null)
                        treeNodeIsVisual3D = true;
                }
 
                Debug.Assert( treeNodeFO.IsValid || (treeNodeVisual3D != null),
                    "We should not be trying to instantiate a node that is neither FrameworkElement nor FrameworkContentElement.  A type check should have been done when Type is set");
 
                // And here's the bool we'll use to make the decision.
                bool treeNodeIsFE = treeNodeFO.IsFE;
 
                // Handle FE/FCE-specific optimizations
 
                if (!treeNodeIsVisual3D)
                {
                    // Postpone "Initialized" event
                    NewNodeBeginInit( treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE );
 
                    // Set the resource reference flags
                    if (StyleHelper.HasResourceDependentsForChild(_childIndex, ref resourceDependents))
                    {
                        treeNodeFO.HasResourceReference = true;
                    }
 
                    // Update the two chains that tracks all the nodes created
                    //  from all the FrameworkElementFactory of this Style.
                    UpdateChildChains( _childName, _childIndex,
                        treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE,
                        affectedChildren, ref noChildIndexChildren );
 
                    // All FrameworkElementFactory-created elements point to the object
                    //  whose Style.VisualTree definition caused all this to occur
                    NewNodeStyledParentProperty( container, isContainerAnFE, treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE );
 
                    // Initialize the per-instance data for the new element.  This
                    // needs to be done before any properties are invalidated.
                    if (_childIndex != -1)
                    {
                        Debug.Assert( _frameworkTemplate != null );
 
                        StyleHelper.CreateInstanceDataForChild(dataField, container, treeNode, _childIndex,
                            _frameworkTemplate.HasInstanceValues, ref _frameworkTemplate.ChildRecordFromChildIndex);
                    }
 
                    // If this element needs to know about the Loaded or Unloaded events, set the optimization
                    // bit in the element
 
                    if (HasLoadedChangeHandler)
                    {
                        BroadcastEventHelper.AddHasLoadedChangeHandlerFlagInAncestry(treeNode);
                    }
                }
                else
                {
                    if (_childName != null)
                    {
                        // Add this instance to the child index chain so that it may
                        // be tracked by the style
 
                        affectedChildren.Add(treeNode);
                    }
                    else
                    {
                        // Child nodes with no _childID (hence no _childIndex) are
                        //  tracked on a separate chain that will be appended to the
                        //  main chain for cleanup purposes.
                        if (noChildIndexChildren == null)
                        {
                            noChildIndexChildren = new List<DependencyObject>(4);
                        }
 
                        noChildIndexChildren.Add(treeNode);
                    }
                }
 
 
                // New node is initialized, build tree top down
                // (Node added before children of node)
                if (container == parent)
                {
                    // Set the NameScope on the root of the Template generated tree
                    TemplateNameScope templateNameScope = new TemplateNameScope(container);
                    NameScope.SetNameScope(treeNode, templateNameScope);
 
                    // This is the root of the tree
                    if (isContainerAnFE)
                    {
                        // The root is added to the Visual tree (not logical) for the
                        // case of FrameworkElement parents
                        containerAsFE.TemplateChild = treeNodeFO.FE;
                    }
                    else
                    {
                        // The root is added to the logical tree for the case
                        // of FrameworkContentElement parent.  This is the logical equivalent
                        // to what happens when adding a child to a visual collection.
                        AddNodeToLogicalTree( (FrameworkContentElement)parent, _type,
                            treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE );
                    }
                }
                else
                {
                    // Call parent IAddChild to add treeNodeFO
                    AddNodeToParent( parent, treeNodeFO );
                }
 
                // Either set properties or invalidate them, depending on the type
 
                if (!treeNodeIsVisual3D)
                {
                    // For non-3D content, we need to invalidate any properties that
                    // came from FrameworkElementFactory.SetValue or VisulaTrigger.SetValue
                    // so that they can get picked up.
 
                    Debug.Assert( _frameworkTemplate != null );
                    StyleHelper.InvalidatePropertiesOnTemplateNode(
                                container,
                                treeNodeFO,
                                _childIndex,
                                ref _frameworkTemplate.ChildRecordFromChildIndex,
                                false /*isDetach*/,
                                this);
 
                }
                else
                {
                    // For 3D, which doesn't understand templates, we set the properties directly
                    // onto the newly-instantiated element.
 
                    for (int i = 0; i < PropertyValues.Count; i++)
                    {
                        var propertyValue = PropertyValues[i];
                        if (propertyValue.ValueType == PropertyValueType.Set)
                        {
                            // Get the value out of the table.
                            object o = propertyValue.ValueInternal;
 
 
                            // If it's a freezable that can't be frozen, it's probably not sharable,
                            // so we make a copy of it.
                            Freezable freezableValue = o as Freezable;
                            if (freezableValue != null && !freezableValue.CanFreeze)
                            {
                                o = freezableValue.Clone();
                            }
 
                            // Or, if it's a markup extension, get the value
                            // to set on this property from the MarkupExtension itself.
                            MarkupExtension me = o as MarkupExtension;
                            if (me != null)
                            {
                                ProvideValueServiceProvider serviceProvider = new ProvideValueServiceProvider();
                                serviceProvider.SetData( treeNodeVisual3D, propertyValue.Property );
                                o = me.ProvideValue( serviceProvider );
                            }
 
                            // Finally, set the value onto the object.
                            treeNodeVisual3D.SetValue(propertyValue.Property, o);
 
                        }
                        else
                        {
                            // We don't support resource references, triggers, etc within the 3D content
                            throw new NotSupportedException(SR.Format(SR.Template3DValueOnly, propertyValue.Property) );
                        }
                    }
                }
 
 
                // Build child tree from factories
                FrameworkElementFactory childFactory = _firstChild;
                while (childFactory != null)
                {
                    childFactory.InstantiateTree(
                        dataField,
                        container,
                        treeNode,
                        affectedChildren,
                        ref noChildIndexChildren,
                        ref resourceDependents);
 
                    childFactory = childFactory._nextSibling;
                }
 
                if (!treeNodeIsVisual3D)
                {
                    // Fire "Initialized" event
                    NewNodeEndInit( treeNodeIsFE, treeNodeFO.FE, treeNodeFO.FCE );
                }
            }
            return treeNode;
        }
 
 
        //
        //  Add a child to a parent, using IAddChild.  This has special support for Grid,
        //  to allow backward compatibility with FEF-based templates that have Column/RowDefinition
        //  children directly  under the Grid.
        //
 
        private void AddNodeToParent( DependencyObject parent, FrameworkObject childFrameworkObject )
        {
            Grid parentGrid;
            ColumnDefinition childNodeColumnDefinition;
            RowDefinition childNodeRowDefinition = null;
 
            if (    childFrameworkObject.IsFCE
                &&  (parentGrid = parent as Grid) != null
                &&  (   (childNodeColumnDefinition = childFrameworkObject.FCE as ColumnDefinition) != null
                    ||  (childNodeRowDefinition = childFrameworkObject.FCE as RowDefinition) != null  )
                )
            {
                if (childNodeColumnDefinition != null)
                {
                    parentGrid.ColumnDefinitions.Add(childNodeColumnDefinition);
                }
                else if (childNodeRowDefinition != null)
                {
                    parentGrid.RowDefinitions.Add(childNodeRowDefinition);
                }
            }
            else
            {
                // CALLBACK
                // Inheritable property invalidations will occur due to
                //   OnParentChanged resulting from AddChild
 
                if (!(parent is IAddChild))
                {
                    throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild,
                                                         parent.GetType().Name));
                }
 
                ((IAddChild)parent).AddChild(childFrameworkObject.DO);
            }
        }
 
 
        // This tree is used to instantiate a tree, represented by this factory.
        // It is instantiated as a normal tree without any template optimizations.
        // This is used by designers to inspect a template.
 
        internal FrameworkObject InstantiateUnoptimizedTree()
        {
 
            if (!_sealed)
            {
                throw new InvalidOperationException(SR.FrameworkElementFactoryMustBeSealed);
            }
 
            // Create the object.
 
            FrameworkObject frameworkObject = new FrameworkObject(CreateDependencyObject());
 
            // Mark the beginning of initialization
 
            frameworkObject.BeginInit();
 
            // Set values for this object, taking them from the shared values table.
 
            ProvideValueServiceProvider provideValueServiceProvider = null;
            FrameworkTemplate.SetTemplateParentValues( Name, frameworkObject.DO, _frameworkTemplate, ref provideValueServiceProvider );
 
            // Get the first child
 
            FrameworkElementFactory childFactory = _firstChild;
 
            // If we have children, get this object's IAddChild, because it's going to be a parent.
 
            IAddChild iAddChild = null;
            if( childFactory != null )
            {
                iAddChild = frameworkObject.DO as IAddChild;
                if (iAddChild == null)
                {
                    throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild,
                                                         frameworkObject.DO.GetType().Name));
                }
            }
 
            // Build the children.
 
            while (childFactory != null)
            {
 
                if (childFactory._text != null)
                {
                    iAddChild.AddText(childFactory._text);
 
                }
                else
                {
                    // Use frameworkObject's IAddChild to add this node.
                    FrameworkObject childFrameworkObject = childFactory.InstantiateUnoptimizedTree();
                    AddNodeToParent(frameworkObject.DO, childFrameworkObject );
                }
 
                childFactory = childFactory._nextSibling;
            }
 
            // Mark the end of the initialization phase
 
            frameworkObject.EndInit();
 
            return frameworkObject;
 
        }
 
 
        /// <summary>
        ///     Update the chain of FrameworkElementFactory-created nodes.
        /// </summary>
        /// <remarks>
        ///     We have two collections of child nodes created from all the
        /// FrameworkElementFactory in a single Style.  Some we "care about"
        /// because of property values, triggers, etc.  Others just needed
        /// to be created and put in a tree, and we can stop worrying about
        /// them.  The former is 'affectedChildren', the latter is
        /// 'noChildIndexChildren' so called because the nodes we don't
        /// care about were not assigned a child index.
        /// </remarks>
        private static void UpdateChildChains( string childID, int childIndex,
            bool treeNodeIsFE, FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE,
            List<DependencyObject> affectedChildren, ref List<DependencyObject> noChildIndexChildren )
        {
            if (childID != null)
            {
                // If a child ID exists, then, a valid child index exists as well
                if( treeNodeIsFE )
                {
                    treeNodeFE.TemplateChildIndex = childIndex;
                }
                else
                {
                    treeNodeFCE.TemplateChildIndex = childIndex;
                }
 
                // Add this instance to the child index chain so that it may
                // be tracked by the style
 
                affectedChildren.Add(treeNodeIsFE ? (DependencyObject)treeNodeFE : (DependencyObject)treeNodeFCE);
            }
            else
            {
                // Child nodes with no _childID (hence no _childIndex) are
                //  tracked on a separate chain that will be appended to the
                //  main chain for cleanup purposes.
                if (noChildIndexChildren == null)
                {
                    noChildIndexChildren = new List<DependencyObject>(4);
                }
 
                noChildIndexChildren.Add(treeNodeIsFE ? (DependencyObject)treeNodeFE : (DependencyObject)treeNodeFCE);
            }
        }
 
        /// <summary>
        ///     Call BeginInit on the newly-created node to postpone the
        /// "Initialized" event.
        /// </summary>
        internal static void NewNodeBeginInit( bool treeNodeIsFE,
            FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE )
        {
            if( treeNodeIsFE )
            {
                // Mark the beginning of the initialization phase
                treeNodeFE.BeginInit();
            }
            else
            {
                // Mark the beginning of the initialization phase
                treeNodeFCE.BeginInit();
            }
        }
 
        /// <summary>
        ///     Call EndInit on the newly-created node to fire the
        /// "Initialized" event.
        /// </summary>
        private static void NewNodeEndInit( bool treeNodeIsFE,
            FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE )
        {
            if( treeNodeIsFE )
            {
                // Mark the beginning of the initialization phase
                treeNodeFE.EndInit();
            }
            else
            {
                // Mark the beginning of the initialization phase
                treeNodeFCE.EndInit();
            }
        }
 
        /// <summary>
        ///     Setup the pointers on this FrameworkElementFactory-created
        /// node so we can find our way back to the object whose Style
        /// included this FrameworkElementFactory.
        /// </summary>
        private static void NewNodeStyledParentProperty(
            DependencyObject container, bool isContainerAnFE,
            bool treeNodeIsFE, FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE)
        {
            if( treeNodeIsFE )
            {
                treeNodeFE._templatedParent = container ;
                treeNodeFE.IsTemplatedParentAnFE = isContainerAnFE;
            }
            else
            {
                treeNodeFCE._templatedParent = container ;
                treeNodeFCE.IsTemplatedParentAnFE = isContainerAnFE;
            }
        }
 
        /// <summary>
        ///     When Style.VisualTree is applied to a FrameworkContentElement,
        /// it is actually added to the logical tree because FrameworkContentElement
        /// has no visual tree.
        /// </summary>
        /// <remarks>
        ///     A prime example of trying to shove a square peg into a round hole.
        /// </remarks>
        internal static void AddNodeToLogicalTree( DependencyObject parent, Type type,
            bool treeNodeIsFE, FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE)
        {
            // If the logical parent already has children, then we can't add
            // a logical subtree from the style, since there would be a conflict.
            // Throw an exception in this case.
            FrameworkContentElement logicalParent = parent as FrameworkContentElement;
            if (logicalParent != null)
            {
                IEnumerator childEnumerator = logicalParent.LogicalChildren;
                if (childEnumerator != null && childEnumerator.MoveNext())
                {
                    throw new InvalidOperationException(SR.Format(SR.AlreadyHasLogicalChildren,
                                                          parent.GetType().Name));
                }
            }
 
            IAddChild  addChildParent = parent as IAddChild;
            if (addChildParent == null)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotHookupFCERoot,
                                                          type.Name));
            }
            else
            {
                if (treeNodeFE != null)
                {
                    addChildParent.AddChild(treeNodeFE);
                }
                else
                {
                    addChildParent.AddChild(treeNodeFCE);
                }
            }
        }
 
        // This method is also used by XamlStyleSerializer to decide whether
        // or not to emit the Name attribute for a VisualTree node.
        internal bool IsChildNameValid(string childName)
        {
            return !childName.StartsWith(AutoGenChildNamePrefix, StringComparison.Ordinal);
        }
 
        private string GenerateChildName()
        {
            string childName = AutoGenChildNamePrefix + AutoGenChildNamePostfix.ToString(CultureInfo.InvariantCulture);
 
            Interlocked.Increment(ref AutoGenChildNamePostfix);
 
            return childName;
        }
 
 
        private void ApplyAutoAliasRules()
        {
            // See also StyleHelper.ApplyAutoAliasRules, which performs this auto-aliasing
            // for non-FEF (Baml) templates.
 
            if (typeof(ContentPresenter).IsAssignableFrom(_type))
            {
                // ContentPresenter auto-aliases Content, ContentTemplate, and
                // ContentTemplateSelector to respective properties on the
                // styled parent.
 
                // The prefix is obtained from the ContentSource property.
                // If this is null, user is explicitly asking for no auto-aliasing.
                object o = GetValue(ContentPresenter.ContentSourceProperty);
                string prefix = (o == DependencyProperty.UnsetValue) ? "Content" : (string)o;
 
                // if Content is previously set, do nothing
                if (!String.IsNullOrEmpty(prefix) && !IsValueDefined(ContentPresenter.ContentProperty))
                {
                    // find source properties, using prefix
                    Debug.Assert(_frameworkTemplate != null, "ContentPresenter is an FE and can only have a FrameworkTemplate");
                    Type targetType = _frameworkTemplate.TargetTypeInternal;
 
                    DependencyProperty dpContent = DependencyProperty.FromName(prefix, targetType);
                    DependencyProperty dpContentTemplate = DependencyProperty.FromName($"{prefix}Template", targetType);
                    DependencyProperty dpContentTemplateSelector = DependencyProperty.FromName($"{prefix}TemplateSelector", targetType);
                    DependencyProperty dpContentStringFormat = DependencyProperty.FromName($"{prefix}StringFormat", targetType);
 
                    // if desired source for Content doesn't exist, report an error
                    if (dpContent == null && o != DependencyProperty.UnsetValue)
                    {
                        throw new InvalidOperationException(SR.Format(SR.MissingContentSource, prefix, targetType));
                    }
 
                    // auto-alias the Content property
                    if (dpContent != null)
                    {
                        SetValue(ContentPresenter.ContentProperty, new TemplateBindingExtension(dpContent));
                    }
 
                    // auto-alias the remaining properties if none of them are previously set
                    if (!IsValueDefined(ContentPresenter.ContentTemplateProperty) &&
                        !IsValueDefined(ContentPresenter.ContentTemplateSelectorProperty) &&
                        !IsValueDefined(ContentPresenter.ContentStringFormatProperty))
                    {
                        if (dpContentTemplate != null)
                            SetValue(ContentPresenter.ContentTemplateProperty, new TemplateBindingExtension(dpContentTemplate));
                        if (dpContentTemplateSelector != null)
                            SetValue(ContentPresenter.ContentTemplateSelectorProperty, new TemplateBindingExtension(dpContentTemplateSelector));
                        if (dpContentStringFormat != null)
                            SetValue(ContentPresenter.ContentStringFormatProperty, new TemplateBindingExtension(dpContentStringFormat));
                    }
                }
            }
            else if (typeof(GridViewRowPresenter).IsAssignableFrom(_type))
            {
                // GridViewRowPresenter auto-aliases Content and Columns to Content
                // property GridView.ColumnCollection property on the templated parent.
 
                // if Content is previously set, do nothing
                if (!IsValueDefined(GridViewRowPresenter.ContentProperty))
                {
                    // find source property
                    Debug.Assert(_frameworkTemplate != null, "GridViewRowPresenter is an FE and can only have a FrameworkTemplate");
                    Type targetType = _frameworkTemplate.TargetTypeInternal;
 
                    DependencyProperty dpContent = DependencyProperty.FromName("Content", targetType);
 
                    // auto-alias the Content property
                    if (dpContent != null)
                    {
                        SetValue(GridViewRowPresenter.ContentProperty, new TemplateBindingExtension(dpContent));
                    }
                }
 
                // if Columns is previously set, do nothing
                if (!IsValueDefined(GridViewRowPresenter.ColumnsProperty))
                {
                    // auto-alias the Columns property
                    SetValue(GridViewRowPresenter.ColumnsProperty, new TemplateBindingExtension(GridView.ColumnCollectionProperty));
                }
            }
        }
 
 
        private bool IsValueDefined(DependencyProperty dp)
        {
            for (int i = 0; i < PropertyValues.Count; i++)
            {
                var propertyValue = PropertyValues[i];
                if (propertyValue.Property == dp &&
                    (propertyValue.ValueType == PropertyValueType.Set ||
                     propertyValue.ValueType == PropertyValueType.Resource ||
                     propertyValue.ValueType == PropertyValueType.TemplateBinding))
                {
                    return true;
                }
            }
 
            return false;
        }
 
 
        private bool _sealed;
 
        // Synchronized (write locks, lock-free reads): Covered by FrameworkElementFactory instance lock
        /* property */ internal FrugalStructList<System.Windows.PropertyValue> PropertyValues = new FrugalStructList<System.Windows.PropertyValue>();
 
        // Store all the event handlers for this FEF
        // NOTE: We cannot use UnCommonField<T> because that uses property engine
        // storage that can be set only on a DependencyObject
        private EventHandlersStore _eventHandlersStore;
 
        internal bool                   _hasLoadedChangeHandler;
 
        private Type _type;
        private string _text;
        private Func<object> _knownTypeFactory;
        private string _childName;
        internal int _childIndex = -1; // Being used in Style.ProcessTemplateStyles
 
        private FrameworkTemplate _frameworkTemplate;
 
        // Auto-generated ChildID uniqueness
        // Synchronized: Covered by Interlocked.Increment
        private static int AutoGenChildNamePostfix = 1;
        private static string AutoGenChildNamePrefix = "~ChildID";
 
        private FrameworkElementFactory _parent;
        private FrameworkElementFactory _firstChild;
        private FrameworkElementFactory _lastChild;
        private FrameworkElementFactory _nextSibling;
 
        // Instance-based synchronization
        private readonly object _synchronized = new object();
    }
}