File: src\Framework\System\Windows\LogicalTreeHelper.cs
Project: wpf\PresentationFramework.csproj (PresentationFramework)
//---------------------------------------------------------------------------
//
// <copyright file="LogicalTreeHelper.cs" company="Microsoft">
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// Description: The LogicalTreeHelper class contains static methods that are
//  useful for performing common tasks with logical tree nodes.  There's nothing
//  here that the end user can't do themselves - but we do it for them and
//  gather them up here.
//
// History:
//  07/28/2003 : RogerCh - Initial creation
//
//---------------------------------------------------------------------------
 
using System;
using System.Collections;   // In order to use IEnumerator
using System.Diagnostics;
using MS.Utility;           // In order to use SR.Get and SRID
 
namespace System.Windows
{
/*
    public delegate bool ParentTraversalCallback(FrameworkElement parentFE, FrameworkContentElement parentFCE, object data);
    public delegate bool ChildTraversalCallback(FrameworkElement childFE, FrameworkContentElement childFCE, object child, object data);
*/
    
/// <summary>
/// Static helper functions for dealing with the logical tree
/// </summary>
public static class LogicalTreeHelper
{
    //------------------------------------------------------
    //
    //  Constructors
    //
    //------------------------------------------------------
 
    //------------------------------------------------------
    //
    //  Public Properties
    //
    //------------------------------------------------------
 
    // None
    
    //------------------------------------------------------
    //
    //  Public Methods
    //
    //------------------------------------------------------
 
    #region Public Methods
    
    /// <summary>
    /// Given an element in the logical tree to start searching from,
    /// searches all its descendent nodes in the logical tree a node whose Name 
    /// matches the specified elementName.
    /// The given DependencyObject must be either a FrameworkElement or FrameworkContentElement.
    /// </summary>
    /// <remarks>
    /// We're searching in a depth-first manner.  Review this if this turns out 
    ///  to be a performance problem.  We're doing this first because it's easy
    ///  and light on memory usage as compared to breadth-first.
    /// (RogerCh):It would be cool if the DFID (depth-first iterative-deepening)
    ///  algorithm would be useful here.
    /// </remarks>
    public static DependencyObject FindLogicalNode( DependencyObject logicalTreeNode, string elementName )
    {
        if( logicalTreeNode == null )
        {
            throw new ArgumentNullException("logicalTreeNode");
        }
        if( elementName == null )
        {
            throw new ArgumentNullException("elementName");
        }
        if( elementName == String.Empty )
        {
            throw new ArgumentException(SR.Get(SRID.StringEmpty), "elementName");
        }
 
        DependencyObject namedElement = null;
        DependencyObject childNode = null;
 
        // Check given node against named element.
        IFrameworkInputElement selfNode = logicalTreeNode as IFrameworkInputElement;
        if( selfNode != null )
        {
            if( selfNode.Name == elementName )
            {
                namedElement = logicalTreeNode;
            }
        }
 
        if( namedElement == null )
        {
            // Nope, the given node isn't it.  See if we can check children.
            IEnumerator childEnumerator = null;
 
            childEnumerator = LogicalTreeHelper.GetLogicalChildren(logicalTreeNode);
 
            // If we can enumerate, check the children.
            if( childEnumerator != null )
            {
                childEnumerator.Reset();
                while( namedElement == null &&
                       childEnumerator.MoveNext() == true)
                {
                    childNode = childEnumerator.Current as DependencyObject;
 
                    if( childNode != null )
                    {
                        namedElement = FindLogicalNode( childNode, elementName );
                    }
                }
            }
        }
 
        // Return what we can find - may be null.
        return namedElement;
    }
 
    /// <summary>
    /// Get the logical parent of the given DependencyObject.
    /// The given DependencyObject must be either a FrameworkElement or FrameworkContentElement
    /// to have a logical parent.
    /// </summary>
    public static DependencyObject GetParent(DependencyObject current)
    {
        if (current == null)
        {
            throw new ArgumentNullException("current"); 
        }
 
        FrameworkElement fe = current as FrameworkElement;
        if (fe != null)
        {
            return fe.Parent;
        }
 
        FrameworkContentElement fce = current as FrameworkContentElement;
        if (fce != null)
        {
            return fce.Parent;
        }
 
        return null;
    }
 
    /// <summary>
    /// Get the logical children for the given DependencyObject.
    /// The given DependencyObject must be either a FrameworkElement or FrameworkContentElement
    /// to have logical children.
    /// </summary>
    public static IEnumerable GetChildren(DependencyObject current)
    {
        if (current == null)
        {
            throw new ArgumentNullException("current"); 
        }
 
        FrameworkElement fe = current as FrameworkElement;
        if (fe != null)
        {
            return new EnumeratorWrapper(fe.LogicalChildren);
        }
 
        FrameworkContentElement fce = current as FrameworkContentElement;
        if (fce != null)
        {
            return new EnumeratorWrapper(fce.LogicalChildren);
        }
 
        return EnumeratorWrapper.Empty;
    }
 
    /// <summary>
    /// Get the logical children for the given FrameworkElement
    /// </summary>
    public static IEnumerable GetChildren(FrameworkElement current)
    {
        if (current == null)
        {
            throw new ArgumentNullException("current"); 
        }
 
        return new EnumeratorWrapper(current.LogicalChildren);
    }
 
    /// <summary>
    /// Get the logical children for the given FrameworkContentElement
    /// </summary>
    public static IEnumerable GetChildren(FrameworkContentElement current)
    {
        if (current == null)
        {
            throw new ArgumentNullException("current"); 
        }
 
        return new EnumeratorWrapper(current.LogicalChildren);
    }
 
    /// <summary>
    /// Attempts to bring this element into view by originating a RequestBringIntoView event.
    /// </summary>
    public static void BringIntoView(DependencyObject current)
    {
        if (current == null)
        {
            throw new ArgumentNullException("current"); 
        }
 
        FrameworkElement fe = current as FrameworkElement;
        if (fe != null)
        {
            fe.BringIntoView();
        }
 
        FrameworkContentElement fce = current as FrameworkContentElement;
        if (fce != null)
        {
            fce.BringIntoView();
        }
    }
 
/*
    /// <summary>
    // 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
*/    
    #endregion Public Methods
 
    //------------------------------------------------------
    //
    //  Public Events
    //
    //------------------------------------------------------
 
    // None
 
    //------------------------------------------------------
    //
    //  Internal Constructors
    //
    //------------------------------------------------------
 
    // None
 
    //------------------------------------------------------
    //
    //  Internal Properties
    //
    //------------------------------------------------------
 
    // None
    
    //------------------------------------------------------
    //
    //  Internal Methods
    //
    //------------------------------------------------------
 
    #region Internal Methods
 
    internal static void AddLogicalChild(DependencyObject parent, object child)
    {
        if (child != null && parent != null)
        {
            FrameworkElement parentFE = parent as FrameworkElement;
            if (parentFE != null)
            {
                parentFE.AddLogicalChild(child);
            }
            else
            {
                FrameworkContentElement parentFCE = parent as FrameworkContentElement;
                if (parentFCE != null)
                {
                    parentFCE.AddLogicalChild(child);
                }
            }
        }
    }
 
    internal static void AddLogicalChild(FrameworkElement parentFE, FrameworkContentElement parentFCE, object child)
    {
        if (child != null)
        {
            if (parentFE != null)
            {
                parentFE.AddLogicalChild(child);
            }
            else if (parentFCE != null)
            {
                parentFCE.AddLogicalChild(child);
            }
        }
    }
 
    internal static void RemoveLogicalChild(DependencyObject parent, object child)
    {
        if (child != null && parent != null)
        {
            FrameworkElement parentFE = parent as FrameworkElement;
            if (parentFE != null)
            {
                parentFE.RemoveLogicalChild(child);
            }
            else
            {
                FrameworkContentElement parentFCE = parent as FrameworkContentElement;
                if (parentFCE != null)
                {
                    parentFCE.RemoveLogicalChild(child);
                }
            }
        }
    }
 
    internal static void RemoveLogicalChild(FrameworkElement parentFE, FrameworkContentElement parentFCE, object child)
    {
        if (child != null)
        {
            Debug.Assert(parentFE != null || parentFCE != null, "Either parentFE or parentFCE should be non-null");
            if (parentFE != null)
            {
                parentFE.RemoveLogicalChild(child);
            }
            else
            {
                parentFCE.RemoveLogicalChild(child);
            }
        }
    }
 
    internal static IEnumerator GetLogicalChildren(DependencyObject current)
    {
        FrameworkElement fe = current as FrameworkElement;
        if (fe != null)
        {
            return fe.LogicalChildren;
        }
 
        FrameworkContentElement fce = current as FrameworkContentElement;
        if (fce != null)
        {
            return fce.LogicalChildren;
        }
 
        return MS.Internal.Controls.EmptyEnumerator.Instance;
    }
 
    #endregion Internal Methods
 
    //------------------------------------------------------
    //
    //  Internal Events
    //
    //------------------------------------------------------
 
    // None
 
    //------------------------------------------------------
    //
    //  Private Classes
    //
    //------------------------------------------------------
 
    private class EnumeratorWrapper : IEnumerable
    {
        public EnumeratorWrapper(IEnumerator enumerator)
        {
            if (enumerator != null)
            {
                _enumerator = enumerator;
            }
            else
            {
                _enumerator = MS.Internal.Controls.EmptyEnumerator.Instance;
            }
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _enumerator;
        }
 
        IEnumerator _enumerator;
 
 
        internal static EnumeratorWrapper Empty
        {
            get
            {
                if (_emptyInstance == null)
                {
                    _emptyInstance = new EnumeratorWrapper(null);
                }
 
                return _emptyInstance;
            }
        }
 
        static EnumeratorWrapper _emptyInstance;
    }
}
}