/// <summary> /// This method is an alternative to WPF's /// <see cref="VisualTreeHelper.GetParent"/> method, which also /// supports content elements. Keep in mind that for content element, /// this method falls back to the logical tree of the element! /// </summary> /// <param name="child">The item to be processed.</param> /// <returns>The submitted item's parent, if available. Otherwise /// null.</returns> public static DependencyObject GetParentObject(this DependencyObject child) { if (child == null) { return(null); } #if !SILVERLIGHT //handle content elements separately var contentElement = child as ContentElement; if (contentElement != null) { DependencyObject parent = ContentOperations.GetParent(contentElement); if (parent != null) { return(parent); } var fce = contentElement as FrameworkContentElement; return(fce != null ? fce.Parent : null); } #endif // also try searching for parent in framework elements (such as DockPanel, etc) var frameworkElement = child as FrameworkElement; if (frameworkElement != null) { DependencyObject parent = frameworkElement.Parent; if (parent != null) { return(parent); } } //if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper return(VisualTreeHelper.GetParent(child)); }
/// <summary> /// This is a recursive function that walks up the tree Adding or Removing /// HasLoadedChangeHander bits. It also inits the IsLoadedCache on Add. /// </summary> /// <param name="d"> /// Node to update /// </param> /// <param name="addHandler"> /// Is it an AddHandler/ Add Child with Handler Operation /// </param> private static void UpdateHasLoadedChangeHandlerFlagInAncestry(DependencyObject d, bool addHandler) { FrameworkObject fo = new FrameworkObject(d); if (!addHandler) { if (AreThereLoadedChangeHandlersInSubtree(ref fo)) { return; // done } } if (fo.IsValid) { if (fo.SubtreeHasLoadedChangeHandler != addHandler) { DependencyObject coreParent = (fo.IsFE) ? VisualTreeHelper.GetParent(fo.FE) : null; DependencyObject logicalParent = fo.Parent; DependencyObject parent = null; fo.SubtreeHasLoadedChangeHandler = addHandler; // Propagate the change to your visual ancestry if (coreParent != null) { UpdateHasLoadedChangeHandlerFlagInAncestry(coreParent, addHandler); parent = coreParent; } // Propagate the change to your logical ancestry if (logicalParent != null && logicalParent != coreParent) { UpdateHasLoadedChangeHandlerFlagInAncestry(logicalParent, addHandler); if (fo.IsFCE) { parent = logicalParent; } } // Propagate the change to your mentor, if any if (logicalParent == null && coreParent == null) { parent = Helper.FindMentor(fo.DO.InheritanceContext); if (parent != null) { fo.ChangeSubtreeHasLoadedChangedHandler(parent); } } if (addHandler) { // The HasLoadedChangeHandler flag is used for two purposes. // 1. To indicate that the sub-tree starting at the current node has // handlers for Loaded / Unloaded event. So broadcast logic // can walk down that path to fire the events. // 2. To indicate that the IsLoaded cache on the node is valid. // If we are adding a handler: // On the POP side of the recursion, as we come back down from the root, // pull the value of IsLoadedCache from the parent in to the child. if (fo.IsFE) { UpdateIsLoadedCache(fo.FE, parent); } else { UpdateIsLoadedCache(fo.FCE, parent); } } } } else // neither a FE or an FCE { DependencyObject coreParent = null; Visual v; Visual3D v3D; ContentElement ce; // This is neither an FE nor and FCE // Propagate the change to your visual ancestry if ((v = d as Visual) != null) { coreParent = VisualTreeHelper.GetParent(v); } else if ((ce = d as ContentElement) != null) { coreParent = ContentOperations.GetParent(ce); } else if ((v3D = d as Visual3D) != null) { coreParent = VisualTreeHelper.GetParent(v3D); } if (coreParent != null) { UpdateHasLoadedChangeHandlerFlagInAncestry(coreParent, addHandler); } } }
// Token: 0x06000318 RID: 792 RVA: 0x00008B80 File Offset: 0x00006D80 private static void UpdateHasLoadedChangeHandlerFlagInAncestry(DependencyObject d, bool addHandler) { FrameworkObject frameworkObject = new FrameworkObject(d); if (!addHandler && BroadcastEventHelper.AreThereLoadedChangeHandlersInSubtree(ref frameworkObject)) { return; } if (frameworkObject.IsValid) { if (frameworkObject.SubtreeHasLoadedChangeHandler != addHandler) { DependencyObject dependencyObject = frameworkObject.IsFE ? VisualTreeHelper.GetParent(frameworkObject.FE) : null; DependencyObject parent = frameworkObject.Parent; DependencyObject dependencyObject2 = null; frameworkObject.SubtreeHasLoadedChangeHandler = addHandler; if (dependencyObject != null) { BroadcastEventHelper.UpdateHasLoadedChangeHandlerFlagInAncestry(dependencyObject, addHandler); dependencyObject2 = dependencyObject; } if (parent != null && parent != dependencyObject) { BroadcastEventHelper.UpdateHasLoadedChangeHandlerFlagInAncestry(parent, addHandler); if (frameworkObject.IsFCE) { dependencyObject2 = parent; } } if (parent == null && dependencyObject == null) { dependencyObject2 = Helper.FindMentor(frameworkObject.DO.InheritanceContext); if (dependencyObject2 != null) { frameworkObject.ChangeSubtreeHasLoadedChangedHandler(dependencyObject2); } } if (addHandler) { if (frameworkObject.IsFE) { BroadcastEventHelper.UpdateIsLoadedCache(frameworkObject.FE, dependencyObject2); return; } BroadcastEventHelper.UpdateIsLoadedCache(frameworkObject.FCE, dependencyObject2); return; } } } else { DependencyObject dependencyObject3 = null; Visual reference; ContentElement reference2; Visual3D reference3; if ((reference = (d as Visual)) != null) { dependencyObject3 = VisualTreeHelper.GetParent(reference); } else if ((reference2 = (d as ContentElement)) != null) { dependencyObject3 = ContentOperations.GetParent(reference2); } else if ((reference3 = (d as Visual3D)) != null) { dependencyObject3 = VisualTreeHelper.GetParent(reference3); } if (dependencyObject3 != null) { BroadcastEventHelper.UpdateHasLoadedChangeHandlerFlagInAncestry(dependencyObject3, addHandler); } } }