/// <summary> /// Find the VisualTreeItem for the specified visual. /// If the item is not found and is not part of the Snoop UI, /// the tree will be adjusted to include the window the item is in. /// </summary> VisualTreeItem FindItem(object target) { var node = rootVisualTreeItem.FindNode(target); var rootVisual = rootVisualTreeItem.MainVisual; if (node == null) { var visual = target as Visual; if (visual != null && rootVisual != null) { // If target is a part of the SnoopUI, let's get out of here. if (visual.IsDescendantOf(this)) { return(null); } // If not in the root tree, make the root be the tree the visual is in. if (!CommonTreeHelper.IsDescendantOf(visual, rootVisual)) { var presentationSource = PresentationSource.FromVisual(visual); if (presentationSource == null) { return(null); // Something went wrong. At least we will not crash with null ref here. } Root = new VisualItem(presentationSource.RootVisual, null); } } rootVisualTreeItem.Reload(); node = rootVisualTreeItem.FindNode(target); } return(node); }
static VisualTreeItem FindNode(VisualTreeItem currentVisualTreeItem, object target) { // it might be faster to have a map for the lookup // check into this at some point Queue <VisualTreeItem> items = new Queue <VisualTreeItem>(); items.Enqueue(currentVisualTreeItem); while (items.Count > 0) { currentVisualTreeItem = items.Dequeue(); if (currentVisualTreeItem.Target == target) { var chrome = currentVisualTreeItem.Target.Wrap <IChrome>(); if (chrome != null && target is IInputElement) { var root = chrome.Root; if (root != null) { var child = RenderTreeHelper.HitTest(root, Mouse.GetPosition((IInputElement)target)); var node = currentVisualTreeItem.FindNode(child); if (node != null) { return(node); } } } return(currentVisualTreeItem); } foreach (var child in currentVisualTreeItem.Children) { items.Enqueue(child); } } return(null); }