//
        //  This method
        //  1. Is invoked when the TemplateProperty is invalidated on a Control,
        //     Page, PageFunctionBase, ContentPresenter, or a sub-class thereof.
        //
        internal static void DoTemplateInvalidations(
            FrameworkElement            feContainer,
            FrameworkTemplate           oldFrameworkTemplate)
        {
            Debug.Assert(feContainer != null);

            DependencyObject    container;
            HybridDictionary[]  oldTemplateData;
            FrameworkTemplate   newFrameworkTemplate = null;
            object              oldTemplate;
            object              newTemplate;
            bool                newTemplateHasResourceReferences;

            Debug.Assert(feContainer != null);

            // Fetch the per-instance data before it goes away (during Template_get)
            oldTemplateData = StyleHelper.TemplateDataField.GetValue(feContainer);

            // Do immediate pull of Template to refresh the value since the
            // new Template needs to be known at this time to do accurate
            // invalidations
            newFrameworkTemplate = feContainer.TemplateInternal;

            container = feContainer;
            oldTemplate = oldFrameworkTemplate;
            newTemplate = newFrameworkTemplate;
            newTemplateHasResourceReferences = (newFrameworkTemplate != null) ? newFrameworkTemplate.HasResourceReferences : false;

            // If the template wants to watch for the Loaded and/or Unloaded events, set the
            // flag that says we want to receive it.  Otherwise, if it was set in the old template, clear it.
            StyleHelper.UpdateLoadedFlag( container, oldFrameworkTemplate, newFrameworkTemplate );

            if (oldTemplate != newTemplate)
            {
                //
                // Template is changing
                //

                // Set up any per-instance state relating to the new Template
                // We do this here instead of OnTemplateInvalidated because
                // this needs to happen for the *first* Template.
                StyleHelper.UpdateInstanceData(
                    StyleHelper.TemplateDataField,
                    feContainer /* fe */, null /* fce */,
                    null /*oldStyle */, null /* newStyle */,
                    oldFrameworkTemplate, newFrameworkTemplate,
                    InternalFlags.HasTemplateGeneratedSubTree);

                // If this new template has resource references (either for the container
                // or for children in the visual tree), then, mark it so that it will
                // not be ignored during resource change invalidations
                if (newTemplate != null && newTemplateHasResourceReferences)
                {
                    Debug.Assert(feContainer != null);
                    feContainer.HasResourceReference = true;
                }

                // If the template wants to watch for the Loaded and/or Unloaded events, set the
                // flag that says we want to receive it.  Otherwise, if it was set in the old template, clear it.

                UpdateLoadedFlag( container, oldFrameworkTemplate, newFrameworkTemplate );


                // Wipe out VisualTree only if VisualTree factories
                // are changing
                //
                // If the factories are null for both new and old, then, the Template
                // has the opportunity to supply the VisualTree using the "BuildVisualTree"
                // virtual.
                FrameworkElementFactory              oldFactory;
                FrameworkElementFactory              newFactory;
                bool                                 canBuildVisualTree;
                bool                                 hasTemplateGeneratedSubTree;
                FrugalStructList<ContainerDependent> oldContainerDependents;
                FrugalStructList<ContainerDependent> newContainerDependents;

                Debug.Assert(feContainer != null);
                oldFactory = (oldFrameworkTemplate != null) ? oldFrameworkTemplate.VisualTree : null;
                newFactory = (newFrameworkTemplate != null) ? newFrameworkTemplate.VisualTree : null;

                canBuildVisualTree = (oldFrameworkTemplate != null) ? oldFrameworkTemplate.CanBuildVisualTree : false;
                hasTemplateGeneratedSubTree = feContainer.HasTemplateGeneratedSubTree;
                oldContainerDependents = (oldFrameworkTemplate != null) ? oldFrameworkTemplate.ContainerDependents : StyleHelper.EmptyContainerDependents;
                newContainerDependents = (newFrameworkTemplate != null) ? newFrameworkTemplate.ContainerDependents : StyleHelper.EmptyContainerDependents;

                if (hasTemplateGeneratedSubTree)
                {
                    StyleHelper.ClearGeneratedSubTree(oldTemplateData,
                        feContainer /* fe */, null /* fce */,
                        oldFrameworkTemplate );
                }

                // Propagate invalidation for template dependents
                FrugalStructList<ContainerDependent> exclusionContainerDependents =
                    new FrugalStructList<ContainerDependent>();
                StyleHelper.InvalidateContainerDependents(container,
                    ref exclusionContainerDependents,
                    ref oldContainerDependents,
                    ref newContainerDependents);

                // Propagate invalidation for resource references that may be
                // picking stuff from the style's ResourceDictionary
                DoTemplateResourcesInvalidations(container, feContainer, null /*fce*/, oldTemplate, newTemplate);

                Debug.Assert(feContainer != null);
                feContainer.OnTemplateChangedInternal(oldFrameworkTemplate, newFrameworkTemplate);
            }
            else
            {
                //
                // Template is not changing
                //

                // Template was invalidated but didn't change. If the Template created the
                // VisualTree via an override of BuildVisualTree, then, it is
                // wiped out now so that it may be conditionally rebuilt by the
                // custom Template
                if (newFrameworkTemplate != null)
                {
                    if (feContainer.HasTemplateGeneratedSubTree
                        && newFrameworkTemplate.VisualTree == null
                        && !newFrameworkTemplate.HasXamlNodeContent )
                    {
                        StyleHelper.ClearGeneratedSubTree(oldTemplateData, feContainer /* fe */, null /* fce */,
                            oldFrameworkTemplate);

                        // Nothing guarantees that ApplyTemplate actually gets
                        // called, so ask for it explicitly (bug 963163).
                        feContainer.InvalidateMeasure();
                    }
                }
            }
        }