/// <summary> /// Does deep Visual tree walk to retrieve all DocumentPageViews. /// It stops recursing down into visual tree in following situations: /// a) Visual is UIElement and it is not part of Contol Template, /// b) Visual is DocumentPageView. /// </summary> /// <param name="root">FrameworkElement that is part of Control Template.</param> /// <param name="pageViews">Collection of DocumentPageViews; found elements are appended here.</param> /// <returns>Whether collection of DocumentPageViews has been updated.</returns> private static void FindDocumentPageViews(Visual root, List<DocumentPageView> pageViews) { Invariant.Assert(root != null); Invariant.Assert(pageViews != null); if (root is DocumentPageView) { pageViews.Add((DocumentPageView)root); } else { FrameworkElement fe; // Do deep tree walk to retrieve all DocumentPageViews. // It stops recursing down into visual tree in following situations: // a) Visual is UIElement and it is not part of Contol Template, // b) Visual is DocumentPageView. // Add to collection any DocumentPageViews found in the Control Template. int count = root.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual child = root.InternalGetVisualChild(i); fe = child as FrameworkElement; if (fe != null) { if (fe.TemplatedParent != null) { if (fe is DocumentPageView) { pageViews.Add(fe as DocumentPageView); } else { FindDocumentPageViews(fe, pageViews); } } } else { FindDocumentPageViews(child, pageViews); } } } }
// ------------------------------------------------------------------ // Walk visual children and find children UIElements. Performs deep // walk of visual tree, but stops when runs into a UIElement. // All found UIElements are appended to uiElements collection. // // visual - Visual element from which UIElements are extracted. // uiElements - collection of UIElements. // ------------------------------------------------------------------ internal static void GetUIElementsFromVisual(Visual visual, List<UIElement> uiElements) { int count = VisualTreeHelper.GetChildrenCount(visual); for(int i = 0; i < count; i++) { Visual child = visual.InternalGetVisualChild(i); if (child is UIElement) { uiElements.Add((UIElement)(child)); } else { GetUIElementsFromVisual(child, uiElements); } } }
/// <summary> /// Does deep Visual tree walk to retrieve an AdornerDecorator. Because /// AdornerDecorator is supposed to cover all DocumentPageViews, it stops /// recursing down into visual tree in following situations: /// a) Visual is UIElement and it is not part of Contol Template, /// b) Visual is DocumentPageView. /// c) Visual is AdornerDecorator. /// </summary> /// <param name="root">FrameworkElement that is part of Control Template.</param> /// <returns>AdornerDecorator, if found.</returns> private AdornerDecorator FindAdornerDecorator(Visual root) { Invariant.Assert(root != null); FrameworkElement fe; AdornerDecorator adornerDecorator = null; // Do deep Visual tree walk to retrieve an AdornerDecorator. Because // AdornerDecorator is supposed to cover all DocumentPageViews, it stops // recursing down into visual tree in following situations: // a) Visual is UIElement and it is not part of Contol Template, // b) Visual is DocumentPageView. // c) Visual is AdornerDecorator. int count = root.InternalVisualChildrenCount; for(int i = 0; i < count; i++) { Visual child = root.InternalGetVisualChild(i); fe = child as FrameworkElement; if (fe != null) { if (fe.TemplatedParent != null) { if (fe is AdornerDecorator) { adornerDecorator = (AdornerDecorator)fe; } else if (!(fe is DocumentPageView)) { adornerDecorator = FindAdornerDecorator(fe); } // else stop on DocumentPageView } } else { adornerDecorator = FindAdornerDecorator(child); } if (adornerDecorator != null) { break; } } return adornerDecorator; }
// private static bool iterate(Visual parent, IteratorCallback callback) { bool done = false; AutomationPeer peer = null; int count = parent.InternalVisualChildrenCount; for (int i = 0; i < count && !done; i++) { Visual child = parent.InternalGetVisualChild(i); if (child != null && child.CheckFlagsAnd(VisualFlags.IsUIElement) && (peer = CreatePeerForElement((UIElement)child)) != null) { done = callback(peer); } else { done = iterate(child, callback); } } return (done); }
// ------------------------------------------------------------------ // Dump visual children. // ------------------------------------------------------------------ private static void DumpVisualChildren(XmlTextWriter writer, string tagName, Visual visualParent) { int count = VisualTreeHelper.GetChildrenCount(visualParent); if (count>0) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", count.ToString(CultureInfo.InvariantCulture)); for(int i = 0; i < count; i++) { DumpVisual(writer, visualParent.InternalGetVisualChild(i), visualParent); } writer.WriteEndElement(); } }
private void markTreeDirtyHelper(Visual v) { //now walk down and mark all UIElements dirty if(v != null) { if(v.CheckFlagsAnd(VisualFlags.IsUIElement)) { UIElement uie = ((UIElement)v); uie.InvalidateMeasureInternal(); uie.InvalidateArrangeInternal(); } //walk children doing the same, don't stop if they are already dirty since there can //be insulated dirty islands below int cnt = v.InternalVisualChildrenCount; for(int i=0; i<cnt; i++) { Visual child = v.InternalGetVisualChild(i); if (child != null) markTreeDirtyHelper(child); } } }
private void CloneVisualTree(ContainerVisual parent, Visual old) { DrawingVisual visual = new DrawingVisual(); parent.Children.Add(visual); visual.Clip = VisualTreeHelper.GetClip(old); visual.Offset = VisualTreeHelper.GetOffset(old); visual.Transform = VisualTreeHelper.GetTransform(old); visual.Opacity = VisualTreeHelper.GetOpacity(old); visual.OpacityMask = VisualTreeHelper.GetOpacityMask(old); #pragma warning disable 0618 visual.BitmapEffectInput = VisualTreeHelper.GetBitmapEffectInput(old); visual.BitmapEffect = VisualTreeHelper.GetBitmapEffect(old); #pragma warning restore 0618 // snapping guidelines?? DrawingContext dc = visual.RenderOpen(); dc.DrawDrawing(old.GetDrawing()); dc.Close(); int count = VisualTreeHelper.GetChildrenCount(old); for(int i = 0; i < count; i++) { Visual child = old.InternalGetVisualChild(i); CloneVisualTree(visual, child); } }
// private static Visual FindVisibleSibling(Visual parent, Visual child, bool searchForwards) { // // First we figure out the index of the specified child Visual. This is why the runtime // of this method is O(n). int childrenCount = parent.InternalVisualChildrenCount; int childIndex; for (childIndex = 0; childIndex < childrenCount; childIndex++) { Visual current = parent.InternalGetVisualChild(childIndex); if (current == child) { // Found the child. break; } } // // Now that we have the child index, we can go and lookup the sibling. if(searchForwards) return FindVisibleSibling(parent, childIndex+1, searchForwards); // (FindVisibleSibling can deal with out of range indices). else return FindVisibleSibling(parent, childIndex-1, searchForwards); // (FindVisibleSibling can deal with out of range indices). }
private int IndexOf(Visual parent, Visual child, out Visual prevChild) { Visual temp; bool foundIndex = false; prevChild = null; int count = parent.InternalVisualChildrenCount; int i; for(i = 0; i < count; i++) { temp = parent.InternalGetVisualChild(i); if(child == temp) { foundIndex = true; break; } prevChild = temp; } if (foundIndex) return i; else return -1; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ // private static Visual FindVisibleSibling ( Visual parent, int start, bool searchForwards) { int index = start; int childrenCount = parent.InternalVisualChildrenCount; while ( index >= 0 && index < childrenCount ) { Visual sibling = parent.InternalGetVisualChild(index); // if its visible or something other than a UIElement keep it if ( !(sibling is UIElement) || (((UIElement)sibling).Visibility == Visibility.Visible ) ) return sibling; index += searchForwards ? 1 : -1; } return null; }
//-------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods private static void iterate(Visual parent, List<AutomationPeer> peers) { AutomationPeer peer = null; int count = parent.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual child = parent.InternalGetVisualChild(i); if (child != null && child.CheckFlagsAnd(VisualFlags.IsUIElement) && (peer = UIElementAutomationPeer.CreatePeerForElement((UIElement)child)) != null) { peers.Add(peer); } else { iterate(child, peers); } } }
internal static Visual FindVisualByType(Visual parent, Type type) { if (parent != null) { int count = parent.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual visual = parent.InternalGetVisualChild(i); if (!type.IsInstanceOfType(visual)) { visual = FindVisualByType(visual, type); } if (visual != null) { return visual; } } } return null; }
/// <summary> /// Recursively resets IsLayoutSuspended flag on all visuals of the whole v's sub tree. /// For UIElements also re-inserts the UIElement into Measure and / or Arrange update queues /// if necessary. /// </summary> internal static void PropagateResumeLayout(Visual parent, Visual v) { if(v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) return; //the subtree is already active - happens when new elements are added to the active tree //elements are created layout-active so they don't need to be specifically unsuspended //no need to walk down in this case //if(!v.CheckFlagsAnd(VisualFlags.IsLayoutSuspended)) return; //that can be true only on top of recursion, if suspended v is being connected to suspended parent. bool parentIsSuspended = parent == null ? false : parent.CheckFlagsAnd(VisualFlags.IsLayoutSuspended); uint parentTreeLevel = parent == null ? 0 : parent.TreeLevel; if(parentIsSuspended) return; v.SetFlags(false, VisualFlags.IsLayoutSuspended); v.TreeLevel = parentTreeLevel + 1; if (v.CheckFlagsAnd(VisualFlags.IsUIElement)) { // re-insert UIElement into the update queues UIElement e = (UIElement)v; Invariant.Assert(!e.MeasureInProgress && !e.ArrangeInProgress); bool requireMeasureUpdate = e.MeasureDirty && !e.NeverMeasured && (e.MeasureRequest == null); bool requireArrangeUpdate = e.ArrangeDirty && !e.NeverArranged && (e.ArrangeRequest == null); ContextLayoutManager contextLayoutManager = (requireMeasureUpdate || requireArrangeUpdate) ? ContextLayoutManager.From(e.Dispatcher) : null; if (requireMeasureUpdate) { contextLayoutManager.MeasureQueue.Add(e); } if (requireArrangeUpdate) { contextLayoutManager.ArrangeQueue.Add(e); } } int count = v.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual cv = v.InternalGetVisualChild(i); if (cv != null) { PropagateResumeLayout(v, cv); } } }
/// <summary> /// Recursively propagates IsLayoutSuspended flag down to the whole v's sub tree. /// </summary> internal static void PropagateSuspendLayout(Visual v) { if(v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) return; //the subtree is already suspended - happens when already suspended tree is further disassembled //no need to walk down in this case if(v.CheckFlagsAnd(VisualFlags.IsLayoutSuspended)) return; // (bug # 1623922) assert that a UIElement has not being // removed from the visual tree while updating layout. if ( Invariant.Strict && v.CheckFlagsAnd(VisualFlags.IsUIElement) ) { UIElement e = (UIElement)v; Invariant.Assert(!e.MeasureInProgress && !e.ArrangeInProgress); } v.SetFlags(true, VisualFlags.IsLayoutSuspended); v.TreeLevel = 0; int count = v.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual cv = v.InternalGetVisualChild(i); if (cv != null) { PropagateSuspendLayout(cv); } } }