FrameworkElementFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / FrameworkElementFactory.cs / 1305600 / FrameworkElementFactory.cs

                            using System; 
using System.Reflection;
using System.Windows.Threading;
using System.Threading;
using System.Windows.Baml2006; 
using System.Windows.Controls;
using System.Windows.Data; 
using System.Windows.Markup; 
using System.Windows.Media;
using System.Windows.Media.Animation; 
using System.Windows.Documents;
using System.Security.Permissions;
using System.Collections;               // For ArrayList
using System.Collections.Generic; 
using System.Collections.Specialized;   // HybridDictionary
using System.Diagnostics;               // For Debug.Assert 
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
{ 
    ///  
    ///     Templating instance representation
    ///  
    [Localizability(LocalizationCategory.NeverLocalize)]
    public class FrameworkElementFactory
    {
        ///  
        ///     Construction
        ///  
        public FrameworkElementFactory() : this(null, null) 
        {
            // Forwarding 
        }

        /// 
        ///     Construction 
        /// 
        /// Type of instance to create 
        public FrameworkElementFactory(Type type) : this(type, null) 
        {
            // Forwarding 
        }

        /// 
        ///     Construction 
        /// 
        /// Text to add 
        public FrameworkElementFactory(string text) : this(null, null) 
        {
            Text = text; 
        }

        /// 
        ///     Construction 
        /// 
        /// Type of instance to create 
        /// Style identifier 
        public FrameworkElementFactory(Type type, string name)
        { 
            Type = type;
            Name = name;
        }
 

        ///  
        ///     Type of object that the factory will produce 
        /// 
        public Type Type 
        {
            get { return _type; }
            set
            { 
                if (_sealed)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
                }
 
                if (_text != null)
                {
                    throw new InvalidOperationException(SR.Get(SRID.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.Get(SRID.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;
            }
        } 

        ///  
        ///     Text string that the factory will produce 
        /// 
        public string Text 
        {
            get { return _text; }
            set
            { 
                if (_sealed)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
                }
 
                if (_firstChild != null)
                {
                    throw new InvalidOperationException(SR.Get(SRID.FrameworkElementFactoryCannotAddText));
                } 

                if ( value == null ) 
                { 
                    throw new ArgumentNullException("value");
                } 

                _text = value;
            }
        } 

        ///  
        ///     Style identifier 
        /// 
        public string Name 
        {
            get { return _childName; }
            set
            { 
                if (_sealed)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
                }
                if (value == string.Empty) 
                {
                    throw new ArgumentException(SR.Get(SRID.NameNotEmptyString));
                }
 
                _childName = value;
            } 
        } 

 
        /// 
        ///     Add a factory child to this factory
        /// 
        /// Child to add 
        public void AppendChild(FrameworkElementFactory child)
        { 
            if (_sealed) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
            }

            if (child == null)
            { 
                throw new ArgumentNullException("child");
            } 
 
            if (child._parent != null)
            { 
                throw new ArgumentException(SR.Get(SRID.FrameworkElementFactoryAlreadyParented));
            }

            if (_text != null) 
            {
                throw new InvalidOperationException(SR.Get(SRID.FrameworkElementFactoryCannotAddText)); 
            } 

            // Build tree of factories 
            if (_firstChild == null)
            {
                _firstChild = child;
                _lastChild = child; 
            }
            else 
            { 
                _lastChild._nextSibling = child;
                _lastChild = child; 
            }

            child._parent = this;
        } 

        ///  
        ///     Simple value set on template child 
        /// 
        /// Dependent property 
        /// Value to set
        public void SetValue(DependencyProperty dp, object value)
        {
            if (_sealed) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
            } 

            if (dp == null) 
            {
                throw new ArgumentNullException("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.Get(SRID.InvalidPropertyValue, value, dp.Name));
            }

            // Styling the logical tree is not supported 
            if (StyleHelper.IsStylingLogicalTree(dp, value))
            { 
                throw new NotSupportedException(SR.Get(SRID.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.Get(SRID.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); 
            }
        }

        ///  
        ///     Set up data binding on template child
        ///  
        /// Dependent property 
        /// Description of binding
        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); 
        }
 
        ///  
        ///     Resource binding on template child
        ///  
        /// Dependent property
        /// Resource identifier
        public void SetResourceReference(DependencyProperty dp, object name)
        { 
            if (_sealed)
            { 
                throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
            }
 
            if (dp == null)
            {
                throw new ArgumentNullException("dp");
            } 

            UpdatePropertyValueList( dp, PropertyValueType.Resource, name ); 
        } 

        ///  
        ///     Add an event handler for the given routed event. This action applies to the instances created by this factory
        /// 
        public void AddHandler(RoutedEvent routedEvent, Delegate handler)
        { 
            // HandledEventToo defaults to false
            // Call forwarded 
            AddHandler(routedEvent, handler, false); 
        }
 
        /// 
        ///     Add an event handler for the given routed event. This action applies to the instances created by this factory
        /// 
        public void AddHandler(RoutedEvent routedEvent, Delegate handler, bool handledEventsToo) 
        {
            if (_sealed) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory"));
            } 

            if (routedEvent == null)
            {
                throw new ArgumentNullException("routedEvent"); 
            }
 
            if (handler == null) 
            {
                throw new ArgumentNullException("handler"); 
            }

            if (handler.GetType() != routedEvent.HandlerType)
            { 
                throw new ArgumentException(SR.Get(SRID.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; 
            }
        } 
 
        /// 
        ///     Remove an event handler for the given routed event. This action applies to the instances created by this factory 
        /// 
        public void RemoveHandler(RoutedEvent routedEvent, Delegate handler)
        {
            if (_sealed) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "FrameworkElementFactory")); 
            } 

            if (routedEvent == null) 
            {
                throw new ArgumentNullException("routedEvent");
            }
 
            if (handler == null)
            { 
                throw new ArgumentNullException("handler"); 
            }
 
            if (handler.GetType() != routedEvent.HandlerType)
            {
                throw new ArgumentException(SR.Get(SRID.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; 
                    }
                }
            }
        } 

        ///  
        ///     Store all the event handlers for this FEF 
        /// 
        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; }
        } 

 
 
        /// 
        ///     Given a set of values for the PropertyValue struct, put that in 
        /// to the PropertyValueList, overwriting any existing entry.
        /// 
        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); 
                } 
            }
        } 

        /// 
        ///     Create a DependencyObject instance of the specified type
        ///  
        /// 
        ///     By default, reflection is used to create the instance. For 
        ///     best perf, override this and do specific construction 
        /// 
        /// New instance 
        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);
        }
 
        /// 
        ///     FrameworkElementFactory mutability state 
        ///  
        public bool IsSealed
        { 
            get { return _sealed; }
        }

 
        /// 
        ///     Parent factory 
        ///  
        public FrameworkElementFactory Parent
        { 
            get { return _parent; }
        }

        ///  
        ///     First child factory
        ///  
        public FrameworkElementFactory FirstChild 
        {
            get { return _firstChild; } 
        }

        /// 
        ///     Next sibling factory 
        /// 
        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++) 
            {
                if (PropertyValues[i].ValueType == PropertyValueType.Set && 
                    PropertyValues[i].Property == dp) 
                {
                    // Found a Set record, return the value 
                    return PropertyValues[i].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.Get(SRID.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.Get(SRID.TypeMustImplementIAddChild, _type.Name)); 
                }
            }

            ApplyAutoAliasRules(); 

            if ((_childName != null) && (_childName != String.Empty)) 
            { 
                // ChildName provided
                if (!IsChildNameValid(_childName)) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.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           dataField,
                DependencyObject                            container,
                DependencyObject                            parent, 
                List                      affectedChildren,
            ref List                      noChildIndexChildren, 
            ref FrugalStructList    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.Get(SRID.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(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++) 
                    {
                        if (PropertyValues[i].ValueType == PropertyValueType.Set)
                        {
                            // Get the value out of the table. 
                            object o = PropertyValues[i].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, PropertyValues[i].Property ); 
                                o = me.ProvideValue( serviceProvider );
                            } 
 
                            // Finally, set the value onto the object.
                            treeNodeVisual3D.SetValue(PropertyValues[i].Property, o); 

                        }

                        else 
                        {
                            // We don't support resource references, triggers, etc within the 3D content 
                            throw new NotSupportedException(SR.Get(SRID.Template3DValueOnly, PropertyValues[i].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.Get(SRID.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.Get(SRID.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.Get(SRID.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; 
 
        }
 

        /// 
        ///     Update the chain of FrameworkElementFactory-created nodes.
        ///  
        /// 
        ///     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.
        ///  
        private static void UpdateChildChains( string childID, int childIndex,
            bool treeNodeIsFE, FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE, 
            List affectedChildren, ref List 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(4); 
                } 

                noChildIndexChildren.Add(treeNodeIsFE ? (DependencyObject)treeNodeFE : (DependencyObject)treeNodeFCE); 
            }
        }

        ///  
        ///     Call BeginInit on the newly-created node to postpone the
        /// "Initialized" event. 
        ///  
        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();
            }
        }
 
        /// 
        ///     Call EndInit on the newly-created node to fire the 
        /// "Initialized" event. 
        /// 
        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();
            }
        } 

        ///  
        ///     Setup the pointers on this FrameworkElementFactory-created 
        /// node so we can find our way back to the object whose Style
        /// included this FrameworkElementFactory. 
        /// 
        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;
            } 
        } 

        ///  
        ///     When Style.VisualTree is applied to a FrameworkContentElement,
        /// it is actually added to the logical tree because FrameworkContentElement
        /// has no visual tree.
        ///  
        /// 
        ///     A prime example of trying to shove a square peg into a round hole. 
        ///  
        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.Get(SRID.AlreadyHasLogicalChildren,
                                                          parent.GetType().Name));
                } 
            }
 
            IAddChild  addChildParent = parent as IAddChild; 
            if (addChildParent == null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.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.Get(SRID.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++) 
            {
                if (PropertyValues[i].Property == dp && 
                    (PropertyValues[i].ValueType == PropertyValueType.Set || 
                     PropertyValues[i].ValueType == PropertyValueType.Resource ||
                     PropertyValues[i].ValueType == PropertyValueType.TemplateBinding)) 
                {
                    return true;
                }
            } 

            return false; 
        } 

 
        private bool _sealed;

        // Synchronized (write locks, lock-free reads): Covered by FrameworkElementFactory instance lock
        /* property */ internal FrugalStructList PropertyValues = new FrugalStructList(); 

        // Store all the event handlers for this FEF 
        // NOTE: We cannot use UnCommonField 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 _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 object _synchronized = new object();
    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK