Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / DescendentsWalker.cs / 1 / DescendentsWalker.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using MS.Utility;
using System.Windows.Controls.Primitives;
namespace System.Windows
{
///
/// This class iterates and callsback for
/// each descendent in a given subtree
///
internal class DescendentsWalker : DescendentsWalkerBase
{
#region Construction
public DescendentsWalker(TreeWalkPriority priority, VisitedCallback callback) :
this(priority, callback, default(T))
{
// Forwarding
}
public DescendentsWalker(TreeWalkPriority priority, VisitedCallback callback, T data)
: base(priority)
{
_callback = callback;
_data = data;
}
#endregion Construction
///
/// Start Iterating through the current subtree
///
public void StartWalk(DependencyObject startNode)
{
// Don't skip starting node
StartWalk(startNode, false);
}
///
/// Start Iterating through the current subtree
///
public virtual void StartWalk(DependencyObject startNode, bool skipStartNode)
{
_startNode = startNode;
bool continueWalk = true;
if (!skipStartNode)
{
if (FrameworkElement.DType.IsInstanceOfType(_startNode) ||
FrameworkContentElement.DType.IsInstanceOfType(_startNode))
{
// Callback for the root of the subtree
continueWalk = _callback(_startNode, _data);
}
}
if (continueWalk)
{
// Iterate through the children of the root
IterateChildren(_startNode);
}
}
///
/// Given a DependencyObject, see if it's any of the types we know
/// to have children. If so, call VisitNode on each of its children.
///
private void IterateChildren(DependencyObject d)
{
_recursionDepth++;
if (FrameworkElement.DType.IsInstanceOfType(d))
{
FrameworkElement fe = (FrameworkElement) d;
bool hasLogicalChildren = fe.HasLogicalChildren;
// FrameworkElement have both a visual and a logical tree.
// Sometimes we want to hit Visual first, sometimes Logical.
if (_priority == TreeWalkPriority.VisualTree)
{
WalkFrameworkElementVisualThenLogicalChildren(fe, hasLogicalChildren);
}
else if (_priority == TreeWalkPriority.LogicalTree)
{
WalkFrameworkElementLogicalThenVisualChildren(fe, hasLogicalChildren);
}
else
{
Debug.Assert( false, "Tree walk priority should be Visual first or Logical first - but this instance of DescendentsWalker has an invalid priority setting that's neither of the two." );
}
}
else if (FrameworkContentElement.DType.IsInstanceOfType(d))
{
// FrameworkContentElement only has a logical tree, so we
// Walk logical children
FrameworkContentElement fce = d as FrameworkContentElement;
if (fce.HasLogicalChildren)
{
WalkLogicalChildren( null, fce, fce.LogicalChildren );
}
}
else
{
// Neither a FrameworkElement nor FrameworkContentElement. See
// if it's a Visual and if so walk the Visual collection
Visual v = d as Visual;
if (v != null)
{
WalkVisualChildren(v);
}
else
{
Visual3D v3D = d as Visual3D;
if (v3D != null)
{
WalkVisualChildren(v3D);
}
}
}
_recursionDepth--;
}
///
/// Given a object of type Visual, call VisitNode on each of its
/// Visual children.
///
private void WalkVisualChildren( Visual v )
{
v.IsVisualChildrenIterationInProgress = true;
try
{
int count = v.InternalVisual2DOr3DChildrenCount;
for(int i = 0; i < count; i++)
{
DependencyObject childVisual = v.InternalGet2DOr3DVisualChild(i);
if (childVisual != null)
{
VisitNode(childVisual);
}
}
}
finally
{
v.IsVisualChildrenIterationInProgress = false;
}
}
///
/// Given a object of type Visual3D, call VisitNode on each of its
/// children.
///
private void WalkVisualChildren( Visual3D v )
{
v.IsVisualChildrenIterationInProgress = true;
try
{
int count = v.InternalVisual2DOr3DChildrenCount;
for(int i = 0; i < count; i++)
{
DependencyObject childVisual = v.InternalGet2DOr3DVisualChild(i);
if (childVisual != null)
{
VisitNode(childVisual);
}
}
}
finally
{
v.IsVisualChildrenIterationInProgress = false;
}
}
///
/// Given an enumerator for Logical children, call VisitNode on each
/// of the nodes in the enumeration.
///
private void WalkLogicalChildren(
FrameworkElement feParent,
FrameworkContentElement fceParent,
IEnumerator logicalChildren )
{
if (feParent != null)
feParent.IsLogicalChildrenIterationInProgress = true;
else
fceParent.IsLogicalChildrenIterationInProgress = true;
try
{
if (logicalChildren != null)
{
while (logicalChildren.MoveNext())
{
DependencyObject child = logicalChildren.Current as DependencyObject;
if (child != null)
{
VisitNode(child);
}
}
}
}
finally
{
if (feParent != null)
feParent.IsLogicalChildrenIterationInProgress = false;
else
fceParent.IsLogicalChildrenIterationInProgress = false;
}
}
///
/// FrameworkElement objects have both a visual and a logical tree.
/// This variant walks the visual children first
///
///
/// It calls the generic WalkVisualChildren, but doesn't call the
/// generic WalkLogicalChildren because there are shortcuts we can take
/// to be smarter than the generic logical children walk.
///
private void WalkFrameworkElementVisualThenLogicalChildren(
FrameworkElement feParent, bool hasLogicalChildren )
{
WalkVisualChildren( feParent );
//
// If a popup is attached to the framework element visit each popup node.
//
List registeredPopups = Popup.RegisteredPopupsField.GetValue(feParent);
if (registeredPopups != null)
{
foreach (Popup p in registeredPopups)
{
VisitNode(p);
}
}
feParent.IsLogicalChildrenIterationInProgress = true;
try
{
// Optimized variant of WalkLogicalChildren
if (hasLogicalChildren)
{
IEnumerator logicalChildren = feParent.LogicalChildren;
if (logicalChildren != null)
{
while (logicalChildren.MoveNext())
{
object current = logicalChildren.Current;
FrameworkElement fe = current as FrameworkElement;
if (fe != null)
{
// For the case that both parents are identical, this node should
// have already been visited when walking through visual
// children, hence we short-circuit here
if (VisualTreeHelper.GetParent(fe) != fe.Parent)
{
VisitNode(fe);
}
}
else
{
FrameworkContentElement fce = current as FrameworkContentElement;
if (fce != null)
{
VisitNode(fce);
}
}
}
}
}
}
finally
{
feParent.IsLogicalChildrenIterationInProgress = false;
}
}
///
/// FrameworkElement objects have both a visual and a logical tree.
/// This variant walks the logical children first
///
///
/// It calls the generic WalkLogicalChildren, but doesn't call the
/// generic WalkVisualChildren because there are shortcuts we can take
/// to be smarter than the generic visual children walk.
///
private void WalkFrameworkElementLogicalThenVisualChildren(
FrameworkElement feParent, bool hasLogicalChildren)
{
if (hasLogicalChildren)
{
WalkLogicalChildren( feParent, null, feParent.LogicalChildren );
}
feParent.IsVisualChildrenIterationInProgress = true;
try
{
// Optimized variant of WalkVisualChildren
int count = feParent.InternalVisualChildrenCount;
for(int i = 0; i < count; i++)
{
Visual child = feParent.InternalGetVisualChild(i);
if (child != null && FrameworkElement.DType.IsInstanceOfType(child))
{
// For the case that both parents are identical, this node should
// have already been visited when walking through logical
// children, hence we short-circuit here
if (VisualTreeHelper.GetParent(child) != ((FrameworkElement) child).Parent)
{
VisitNode(child);
}
}
}
}
finally
{
feParent.IsVisualChildrenIterationInProgress = false;
}
//
// If a popup is attached to the framework element visit each popup node.
//
List registeredPopups = Popup.RegisteredPopupsField.GetValue(feParent);
if (registeredPopups != null)
{
foreach (Popup p in registeredPopups)
{
VisitNode(p);
}
}
}
private void VisitNode(FrameworkElement fe)
{
if (_recursionDepth <= MAX_TREE_DEPTH)
{
// For the case when the collection contains the node
// being visted, we do not need to visit it again. Also
// this node will not be visited another time because
// any node can be reached at most two times, once
// via its visual parent and once via its logical parent
int index = _nodes.IndexOf(fe);
// If index is not -1, then fe was in the list, remove it
if (index != -1)
{
_nodes.RemoveAt(index);
}
else
{
// A node will be visited a second time only if it has
// different non-null logical and visual parents.
// Hence that is the only case that we need to
// remember this node, to avoid duplicate callback for it
DependencyObject dependencyObjectParent = VisualTreeHelper.GetParent(fe);
DependencyObject logicalParent = fe.Parent;
if (dependencyObjectParent != null && logicalParent != null && dependencyObjectParent != logicalParent)
{
_nodes.Add(fe);
}
_VisitNode(fe);
}
}
else
{
// We suspect a loop here because the recursion
// depth has exceeded the MAX_TREE_DEPTH expected
throw new InvalidOperationException(SR.Get(SRID.LogicalTreeLoop));
}
}
private void VisitNode(DependencyObject d)
{
if (_recursionDepth <= MAX_TREE_DEPTH)
{
if (FrameworkElement.DType.IsInstanceOfType(d))
{
VisitNode(d as FrameworkElement);
}
else if (FrameworkContentElement.DType.IsInstanceOfType(d))
{
_VisitNode(d);
}
else
{
// Iterate through the children of this node
IterateChildren(d);
}
}
else
{
// We suspect a loop here because the recursion
// depth has exceeded the MAX_TREE_DEPTH expected
throw new InvalidOperationException(SR.Get(SRID.LogicalTreeLoop));
}
}
protected virtual void _VisitNode(DependencyObject d)
{
// Callback for this node of the subtree
bool continueWalk = _callback(d, _data);
if (continueWalk)
{
// Iterate through the children of this node
IterateChildren(d);
}
}
protected T Data
{
get
{
return _data;
}
}
private VisitedCallback _callback;
private T _data;
}
///
/// Callback for each visited node
///
internal delegate bool VisitedCallback(DependencyObject d, T data);
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using MS.Utility;
using System.Windows.Controls.Primitives;
namespace System.Windows
{
///
/// This class iterates and callsback for
/// each descendent in a given subtree
///
internal class DescendentsWalker : DescendentsWalkerBase
{
#region Construction
public DescendentsWalker(TreeWalkPriority priority, VisitedCallback callback) :
this(priority, callback, default(T))
{
// Forwarding
}
public DescendentsWalker(TreeWalkPriority priority, VisitedCallback callback, T data)
: base(priority)
{
_callback = callback;
_data = data;
}
#endregion Construction
///
/// Start Iterating through the current subtree
///
public void StartWalk(DependencyObject startNode)
{
// Don't skip starting node
StartWalk(startNode, false);
}
///
/// Start Iterating through the current subtree
///
public virtual void StartWalk(DependencyObject startNode, bool skipStartNode)
{
_startNode = startNode;
bool continueWalk = true;
if (!skipStartNode)
{
if (FrameworkElement.DType.IsInstanceOfType(_startNode) ||
FrameworkContentElement.DType.IsInstanceOfType(_startNode))
{
// Callback for the root of the subtree
continueWalk = _callback(_startNode, _data);
}
}
if (continueWalk)
{
// Iterate through the children of the root
IterateChildren(_startNode);
}
}
///
/// Given a DependencyObject, see if it's any of the types we know
/// to have children. If so, call VisitNode on each of its children.
///
private void IterateChildren(DependencyObject d)
{
_recursionDepth++;
if (FrameworkElement.DType.IsInstanceOfType(d))
{
FrameworkElement fe = (FrameworkElement) d;
bool hasLogicalChildren = fe.HasLogicalChildren;
// FrameworkElement have both a visual and a logical tree.
// Sometimes we want to hit Visual first, sometimes Logical.
if (_priority == TreeWalkPriority.VisualTree)
{
WalkFrameworkElementVisualThenLogicalChildren(fe, hasLogicalChildren);
}
else if (_priority == TreeWalkPriority.LogicalTree)
{
WalkFrameworkElementLogicalThenVisualChildren(fe, hasLogicalChildren);
}
else
{
Debug.Assert( false, "Tree walk priority should be Visual first or Logical first - but this instance of DescendentsWalker has an invalid priority setting that's neither of the two." );
}
}
else if (FrameworkContentElement.DType.IsInstanceOfType(d))
{
// FrameworkContentElement only has a logical tree, so we
// Walk logical children
FrameworkContentElement fce = d as FrameworkContentElement;
if (fce.HasLogicalChildren)
{
WalkLogicalChildren( null, fce, fce.LogicalChildren );
}
}
else
{
// Neither a FrameworkElement nor FrameworkContentElement. See
// if it's a Visual and if so walk the Visual collection
Visual v = d as Visual;
if (v != null)
{
WalkVisualChildren(v);
}
else
{
Visual3D v3D = d as Visual3D;
if (v3D != null)
{
WalkVisualChildren(v3D);
}
}
}
_recursionDepth--;
}
///
/// Given a object of type Visual, call VisitNode on each of its
/// Visual children.
///
private void WalkVisualChildren( Visual v )
{
v.IsVisualChildrenIterationInProgress = true;
try
{
int count = v.InternalVisual2DOr3DChildrenCount;
for(int i = 0; i < count; i++)
{
DependencyObject childVisual = v.InternalGet2DOr3DVisualChild(i);
if (childVisual != null)
{
VisitNode(childVisual);
}
}
}
finally
{
v.IsVisualChildrenIterationInProgress = false;
}
}
///
/// Given a object of type Visual3D, call VisitNode on each of its
/// children.
///
private void WalkVisualChildren( Visual3D v )
{
v.IsVisualChildrenIterationInProgress = true;
try
{
int count = v.InternalVisual2DOr3DChildrenCount;
for(int i = 0; i < count; i++)
{
DependencyObject childVisual = v.InternalGet2DOr3DVisualChild(i);
if (childVisual != null)
{
VisitNode(childVisual);
}
}
}
finally
{
v.IsVisualChildrenIterationInProgress = false;
}
}
///
/// Given an enumerator for Logical children, call VisitNode on each
/// of the nodes in the enumeration.
///
private void WalkLogicalChildren(
FrameworkElement feParent,
FrameworkContentElement fceParent,
IEnumerator logicalChildren )
{
if (feParent != null)
feParent.IsLogicalChildrenIterationInProgress = true;
else
fceParent.IsLogicalChildrenIterationInProgress = true;
try
{
if (logicalChildren != null)
{
while (logicalChildren.MoveNext())
{
DependencyObject child = logicalChildren.Current as DependencyObject;
if (child != null)
{
VisitNode(child);
}
}
}
}
finally
{
if (feParent != null)
feParent.IsLogicalChildrenIterationInProgress = false;
else
fceParent.IsLogicalChildrenIterationInProgress = false;
}
}
///
/// FrameworkElement objects have both a visual and a logical tree.
/// This variant walks the visual children first
///
///
/// It calls the generic WalkVisualChildren, but doesn't call the
/// generic WalkLogicalChildren because there are shortcuts we can take
/// to be smarter than the generic logical children walk.
///
private void WalkFrameworkElementVisualThenLogicalChildren(
FrameworkElement feParent, bool hasLogicalChildren )
{
WalkVisualChildren( feParent );
//
// If a popup is attached to the framework element visit each popup node.
//
List registeredPopups = Popup.RegisteredPopupsField.GetValue(feParent);
if (registeredPopups != null)
{
foreach (Popup p in registeredPopups)
{
VisitNode(p);
}
}
feParent.IsLogicalChildrenIterationInProgress = true;
try
{
// Optimized variant of WalkLogicalChildren
if (hasLogicalChildren)
{
IEnumerator logicalChildren = feParent.LogicalChildren;
if (logicalChildren != null)
{
while (logicalChildren.MoveNext())
{
object current = logicalChildren.Current;
FrameworkElement fe = current as FrameworkElement;
if (fe != null)
{
// For the case that both parents are identical, this node should
// have already been visited when walking through visual
// children, hence we short-circuit here
if (VisualTreeHelper.GetParent(fe) != fe.Parent)
{
VisitNode(fe);
}
}
else
{
FrameworkContentElement fce = current as FrameworkContentElement;
if (fce != null)
{
VisitNode(fce);
}
}
}
}
}
}
finally
{
feParent.IsLogicalChildrenIterationInProgress = false;
}
}
///
/// FrameworkElement objects have both a visual and a logical tree.
/// This variant walks the logical children first
///
///
/// It calls the generic WalkLogicalChildren, but doesn't call the
/// generic WalkVisualChildren because there are shortcuts we can take
/// to be smarter than the generic visual children walk.
///
private void WalkFrameworkElementLogicalThenVisualChildren(
FrameworkElement feParent, bool hasLogicalChildren)
{
if (hasLogicalChildren)
{
WalkLogicalChildren( feParent, null, feParent.LogicalChildren );
}
feParent.IsVisualChildrenIterationInProgress = true;
try
{
// Optimized variant of WalkVisualChildren
int count = feParent.InternalVisualChildrenCount;
for(int i = 0; i < count; i++)
{
Visual child = feParent.InternalGetVisualChild(i);
if (child != null && FrameworkElement.DType.IsInstanceOfType(child))
{
// For the case that both parents are identical, this node should
// have already been visited when walking through logical
// children, hence we short-circuit here
if (VisualTreeHelper.GetParent(child) != ((FrameworkElement) child).Parent)
{
VisitNode(child);
}
}
}
}
finally
{
feParent.IsVisualChildrenIterationInProgress = false;
}
//
// If a popup is attached to the framework element visit each popup node.
//
List registeredPopups = Popup.RegisteredPopupsField.GetValue(feParent);
if (registeredPopups != null)
{
foreach (Popup p in registeredPopups)
{
VisitNode(p);
}
}
}
private void VisitNode(FrameworkElement fe)
{
if (_recursionDepth <= MAX_TREE_DEPTH)
{
// For the case when the collection contains the node
// being visted, we do not need to visit it again. Also
// this node will not be visited another time because
// any node can be reached at most two times, once
// via its visual parent and once via its logical parent
int index = _nodes.IndexOf(fe);
// If index is not -1, then fe was in the list, remove it
if (index != -1)
{
_nodes.RemoveAt(index);
}
else
{
// A node will be visited a second time only if it has
// different non-null logical and visual parents.
// Hence that is the only case that we need to
// remember this node, to avoid duplicate callback for it
DependencyObject dependencyObjectParent = VisualTreeHelper.GetParent(fe);
DependencyObject logicalParent = fe.Parent;
if (dependencyObjectParent != null && logicalParent != null && dependencyObjectParent != logicalParent)
{
_nodes.Add(fe);
}
_VisitNode(fe);
}
}
else
{
// We suspect a loop here because the recursion
// depth has exceeded the MAX_TREE_DEPTH expected
throw new InvalidOperationException(SR.Get(SRID.LogicalTreeLoop));
}
}
private void VisitNode(DependencyObject d)
{
if (_recursionDepth <= MAX_TREE_DEPTH)
{
if (FrameworkElement.DType.IsInstanceOfType(d))
{
VisitNode(d as FrameworkElement);
}
else if (FrameworkContentElement.DType.IsInstanceOfType(d))
{
_VisitNode(d);
}
else
{
// Iterate through the children of this node
IterateChildren(d);
}
}
else
{
// We suspect a loop here because the recursion
// depth has exceeded the MAX_TREE_DEPTH expected
throw new InvalidOperationException(SR.Get(SRID.LogicalTreeLoop));
}
}
protected virtual void _VisitNode(DependencyObject d)
{
// Callback for this node of the subtree
bool continueWalk = _callback(d, _data);
if (continueWalk)
{
// Iterate through the children of this node
IterateChildren(d);
}
}
protected T Data
{
get
{
return _data;
}
}
private VisitedCallback _callback;
private T _data;
}
///
/// Callback for each visited node
///
internal delegate bool VisitedCallback(DependencyObject d, T data);
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TypeDescriptionProviderAttribute.cs
- _ShellExpression.cs
- Collection.cs
- ExtenderProviderService.cs
- TdsParserStateObject.cs
- ArrayList.cs
- ToolStripRenderEventArgs.cs
- OdbcCommand.cs
- ObjectDataSourceStatusEventArgs.cs
- ParameterElement.cs
- DockPatternIdentifiers.cs
- DataSourceProvider.cs
- ToolstripProfessionalRenderer.cs
- storepermission.cs
- ReferentialConstraint.cs
- ToolBarPanel.cs
- XmlUTF8TextWriter.cs
- TreeNodeStyleCollection.cs
- CompilerErrorCollection.cs
- FillRuleValidation.cs
- IPipelineRuntime.cs
- NamespaceTable.cs
- UpDownEvent.cs
- sitestring.cs
- Publisher.cs
- XDeferredAxisSource.cs
- HttpCacheParams.cs
- oledbconnectionstring.cs
- PolicyConversionContext.cs
- CompensationDesigner.cs
- DebugView.cs
- XmlLangPropertyAttribute.cs
- DataViewListener.cs
- MulticastDelegate.cs
- TraversalRequest.cs
- WindowsIdentity.cs
- RawStylusSystemGestureInputReport.cs
- Inline.cs
- IDataContractSurrogate.cs
- HitTestWithPointDrawingContextWalker.cs
- SchemaImporterExtension.cs
- ObjectDataSource.cs
- DescendantOverDescendantQuery.cs
- StoreContentChangedEventArgs.cs
- HttpCookie.cs
- XmlQualifiedName.cs
- assemblycache.cs
- PostBackOptions.cs
- AssemblyHash.cs
- Schema.cs
- TripleDES.cs
- PageVisual.cs
- XamlClipboardData.cs
- SerTrace.cs
- GeometryDrawing.cs
- UIElementParaClient.cs
- PassportPrincipal.cs
- BinaryUtilClasses.cs
- ChannelOptions.cs
- ColumnWidthChangedEvent.cs
- BitmapData.cs
- KeyGesture.cs
- UmAlQuraCalendar.cs
- CommandDesigner.cs
- CollectionBuilder.cs
- parserscommon.cs
- MessageSmuggler.cs
- WebPartDisplayModeCollection.cs
- CryptoApi.cs
- AccessedThroughPropertyAttribute.cs
- CaseInsensitiveOrdinalStringComparer.cs
- BindingMemberInfo.cs
- TrustLevelCollection.cs
- XPathQueryGenerator.cs
- RevocationPoint.cs
- PropertyKey.cs
- DoubleAnimationUsingPath.cs
- TargetException.cs
- GridViewColumnHeader.cs
- UnescapedXmlDiagnosticData.cs
- Parameter.cs
- DataListCommandEventArgs.cs
- SmiRequestExecutor.cs
- MethodRental.cs
- StylusOverProperty.cs
- RoleServiceManager.cs
- CacheChildrenQuery.cs
- XpsS0ValidatingLoader.cs
- ExecutionProperties.cs
- ProfileParameter.cs
- CqlErrorHelper.cs
- BindToObject.cs
- BrushConverter.cs
- ArgumentElement.cs
- GenericNameHandler.cs
- TreeViewImageKeyConverter.cs
- ScriptComponentDescriptor.cs
- SctClaimSerializer.cs
- ApplicationCommands.cs
- TabItemWrapperAutomationPeer.cs