File: src\Framework\MS\Internal\PrePostDescendentsWalker.cs
Project: wpf\PresentationFramework.csproj (PresentationFramework)
//-----------------------------------------------------------------------------
//
// <copyright file="PrePostDescendentsWalker.cs" company="Microsoft">
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// Description:
//     A simple subclass of DescendentsWalker which introduces a second callback
//     which is called after a node's children have been visited.
//
// History:
//  04/13/2004: rruiz:  Introduces class.
//  10/20/2004: rruiz:  Moved class to MS.Internal.
//
//-----------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using MS.Utility;
 
namespace MS.Internal
{
    /// <summary>
    ///     A simple subclass of DescendentsWalker which introduces a second callback
    ///     which is called after a node's children have been visited.
    /// </summary>
    internal class PrePostDescendentsWalker<T> : DescendentsWalker<T>
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
 
        #region Constructors
 
        /// <summary>
        ///     Creates an instances of PrePostDescendentsWalker.
        /// </summary>
        /// <param name="priority">specifies which tree should be visited first</param>
        /// <param name="preCallback">the callback to be called before a node's children are visited</param>
        /// <param name="postCallback">the callback to be called after a node's children are visited</param>
        /// <param name="data">the data passed to each callback</param>
        public PrePostDescendentsWalker(TreeWalkPriority priority, VisitedCallback<T> preCallback, VisitedCallback<T> postCallback, T data) : 
            base(priority, preCallback, data)
        {
            _postCallback = postCallback;
        }
 
        #endregion Constructors 
 
        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
 
        #region Public Methods
 
        /// <summary>
        ///     Starts the walking process for the given node.
        /// </summary>
        /// <param name="startNode">the node to start the walk on</param>
        /// <param name="skipStartNode">whether or not the first node should have the callbacks called on it</param>
        public override void StartWalk(DependencyObject startNode, bool skipStartNode)
        {
            try
            {
                base.StartWalk(startNode, skipStartNode);
            }
            finally
            {
                if (!skipStartNode)
                {
                    if (_postCallback != null)
                    {
                        // This type checking is done in DescendentsWalker.  Doing it here
                        // keeps us consistent.
                        if (FrameworkElement.DType.IsInstanceOfType(startNode) || FrameworkContentElement.DType.IsInstanceOfType(startNode))
                        {
                            _postCallback(startNode, this.Data, _priority == TreeWalkPriority.VisualTree);
                        }
                    }
                }
            }
        }
 
        #endregion Public Methods
        
        //------------------------------------------------------
        //
        //  Protected Methods
        //
        //------------------------------------------------------
 
        #region Protected Methods
 
        /// <summary>
        ///     This method is called for every node touched during a walking of 
        ///     the tree.  Some nodes may not have this called if the preCallback
        ///     returns false - thereby preventing its subtree from being visited.
        /// </summary>
        /// <param name="d">the node to visit</param>
        protected override void _VisitNode(DependencyObject d, bool visitedViaVisualTree)
        {
            try
            {
                base._VisitNode(d, visitedViaVisualTree);
            }
            finally
            {
                if (_postCallback != null)
                {
                    _postCallback(d, this.Data, visitedViaVisualTree);
                }
            }
        }
 
        #endregion Protected Methods      
        
        //------------------------------------------------------
        //
        //  Private Properties
        //
        //------------------------------------------------------        
 
        #region Private Properties
 
        private VisitedCallback<T> _postCallback;
 
        #endregion Private Properties
        
    }
}