Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / 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. // ListregisteredPopups = 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. // ListregisteredPopups = 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. // ListregisteredPopups = 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. // ListregisteredPopups = 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
- CodeAttributeDeclaration.cs
- ParallelRangeManager.cs
- HierarchicalDataSourceConverter.cs
- EdmToObjectNamespaceMap.cs
- ClientSession.cs
- DataKey.cs
- CSharpCodeProvider.cs
- Win32NamedPipes.cs
- SerializationObjectManager.cs
- ScrollProviderWrapper.cs
- DateTimeOffsetStorage.cs
- ToolStripProfessionalLowResolutionRenderer.cs
- SqlSupersetValidator.cs
- CommandPlan.cs
- CharConverter.cs
- ComponentCollection.cs
- NumberAction.cs
- DescendantOverDescendantQuery.cs
- BamlRecordReader.cs
- UnauthorizedWebPart.cs
- ConnectionManagementElement.cs
- ListViewGroupConverter.cs
- DrawingImage.cs
- ContentFileHelper.cs
- CharConverter.cs
- GeneratedCodeAttribute.cs
- Options.cs
- Transform3DCollection.cs
- ControlPropertyNameConverter.cs
- MessageQueue.cs
- WebSysDescriptionAttribute.cs
- LingerOption.cs
- HandleRef.cs
- Model3DCollection.cs
- DateTimeFormatInfoScanner.cs
- QueryInterceptorAttribute.cs
- HelpPage.cs
- SqlClientMetaDataCollectionNames.cs
- ServiceParser.cs
- AnnotationMap.cs
- ObjectStateEntryDbUpdatableDataRecord.cs
- ListControlDesigner.cs
- ChildTable.cs
- OleDbSchemaGuid.cs
- NotificationContext.cs
- ScaleTransform3D.cs
- AppearanceEditorPart.cs
- TextEffect.cs
- ContentPlaceHolder.cs
- CommonDialog.cs
- SiteMapProvider.cs
- SecurityIdentifierElementCollection.cs
- UnsafeNativeMethods.cs
- PathFigure.cs
- Line.cs
- UserControl.cs
- CodeCompiler.cs
- SqlConnectionManager.cs
- SessionPageStatePersister.cs
- SystemEvents.cs
- NativeMethods.cs
- RangeBase.cs
- LassoHelper.cs
- StringFormat.cs
- XmlStreamStore.cs
- StringUtil.cs
- ConstNode.cs
- basevalidator.cs
- PreservationFileReader.cs
- TraceHandlerErrorFormatter.cs
- CompositeDataBoundControl.cs
- SqlDependency.cs
- DataGridViewCellConverter.cs
- Connection.cs
- IdnMapping.cs
- InplaceBitmapMetadataWriter.cs
- ZipIOFileItemStream.cs
- PathGradientBrush.cs
- mediaeventargs.cs
- SortQuery.cs
- AutomationEvent.cs
- ConstraintManager.cs
- DesignTimeResourceProviderFactoryAttribute.cs
- Number.cs
- DataServicePagingProviderWrapper.cs
- AuthStoreRoleProvider.cs
- GeneralTransform3DGroup.cs
- XmlIgnoreAttribute.cs
- DiffuseMaterial.cs
- QueryStringParameter.cs
- PermissionAttributes.cs
- Assert.cs
- DiffuseMaterial.cs
- XmlParserContext.cs
- NavigatorInput.cs
- SmtpDigestAuthenticationModule.cs
- FormViewDeletedEventArgs.cs
- CqlWriter.cs
- InfoCardKeyedHashAlgorithm.cs
- WebPartsPersonalization.cs