/// <summary> /// Invoked when logical parent is changed. This just /// sets the parent pointer. /// </summary> /// <remarks> /// A parent change is considered catastrohpic and results in a large /// amount of invalidations and tree traversals. <cref see="DependencyFastBuild"/> /// is recommended to reduce the work necessary to build a tree /// </remarks> /// <param name="newParent"> /// New parent that was set /// </param> internal void ChangeLogicalParent(DependencyObject newParent) { /////////////////// // OnNewParent: /////////////////// // // -- Approved By The Core Team -- // // Do not allow foreign threads to change the tree. // (This is a noop if this object is not assigned to a Dispatcher.) // // We also need to ensure that the tree is homogenous with respect // to the dispatchers that the elements belong to. // this.VerifyAccess(); if (newParent != null) { newParent.VerifyAccess(); } // Logical Parent must first be dropped before you are attached to a newParent // This mitigates illegal tree state caused by logical child stealing as illustrated in bug 970706 if (_parent != null && newParent != null && _parent != newParent) { throw new System.InvalidOperationException(SR.Get(SRID.HasLogicalParent)); } // Trivial check to avoid loops if (newParent == this) { throw new System.InvalidOperationException(SR.Get(SRID.CannotBeSelfParent)); } // invalid during a VisualTreeChanged event VisualDiagnostics.VerifyVisualTreeChange(this); // Logical Parent implies no InheritanceContext if (newParent != null) { ClearInheritanceContext(); } IsParentAnFE = newParent is FrameworkElement; DependencyObject oldParent = _parent; OnNewParent(newParent); // Update Has[Loaded/Unloaded]Handler Flags BroadcastEventHelper.AddOrRemoveHasLoadedChangeHandlerFlag(this, oldParent, newParent); // Fire Loaded and Unloaded Events BroadcastEventHelper.BroadcastLoadedOrUnloadedEvent(this, oldParent, newParent); /////////////////// // OnParentChanged: /////////////////// // Invalidate relevant properties for this subtree DependencyObject parent = (newParent != null) ? newParent : oldParent; TreeWalkHelper.InvalidateOnTreeChange(/* fe = */ null, /* fce = */ this, parent, (newParent != null)); // If no one has called BeginInit then mark the element initialized and fire Initialized event // (non-parser programmatic tree building scenario) TryFireInitialized(); }