File: System\Windows\DescendentsWalkerBase.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Windows.Media;
using MS.Utility;
 
namespace System.Windows
{
    /// <summary>
    ///     This is a base class to the DescendentsWalker. It is factored out so that 
    ///     FrameworkContextData can store and retrieve it from context local storage 
    ///     in a type agnostic manner.
    /// </summary>
    internal class DescendentsWalkerBase
    {
        #region Construction
 
        protected DescendentsWalkerBase(TreeWalkPriority priority)
        {
            _startNode = null;
            _priority = priority;
            _recursionDepth = 0;
            _nodes = new FrugalStructList<DependencyObject>();
        }
 
        #endregion Construction
 
        internal bool WasVisited(DependencyObject d)
        {
            DependencyObject ancestor = d;
 
            while ((ancestor != _startNode) && (ancestor != null))
            {
                DependencyObject logicalParent;
 
                if (ancestor is FrameworkElement fe)
                {
                    logicalParent = fe.Parent;
                    // FrameworkElement
                    DependencyObject dependencyObjectParent = VisualTreeHelper.GetParent(fe);
                    if (dependencyObjectParent != null && logicalParent != null && dependencyObjectParent != logicalParent)
                    {
                        return _nodes.Contains(ancestor);
                    }
 
                    // Follow visual tree if not null otherwise we follow logical tree
                    if (dependencyObjectParent != null)
                    {
                        ancestor = dependencyObjectParent;
                        continue;
                    }
                }
                else
                {
                    // FrameworkContentElement
                    FrameworkContentElement ancestorFCE = ancestor as FrameworkContentElement;
                    logicalParent = (ancestorFCE != null) ? ancestorFCE.Parent : null;
                }
                ancestor = logicalParent;
            }
            return (ancestor != null);
        }
 
 
        internal DependencyObject _startNode;
        internal TreeWalkPriority _priority;
 
        internal FrugalStructList<DependencyObject> _nodes;
        internal int _recursionDepth;
    }
 
    /// <summary>
    ///     Enum specifying whether visual tree needs
    ///     to be travesed first or the logical tree
    /// </summary>
    internal enum TreeWalkPriority
    {
        /// <summary>
        ///     Traverse Logical Tree first
        /// </summary>
        LogicalTree,
 
        /// <summary>
        ///     Traverse Visual Tree first
        /// </summary>
        VisualTree
    }
}