Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / DescendentsWalker.cs / 1305600 / 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 <= ContextLayoutManager.s_LayoutRecursionLimit) { // 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 <= ContextLayoutManager.s_LayoutRecursionLimit) { 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 <= ContextLayoutManager.s_LayoutRecursionLimit) { // 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 <= ContextLayoutManager.s_LayoutRecursionLimit) { 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
- UInt16Converter.cs
- Geometry.cs
- EndpointDiscoveryElement.cs
- WebPartChrome.cs
- QueryOpcode.cs
- CodeNamespaceImport.cs
- MSAAWinEventWrap.cs
- BufferedGraphics.cs
- ConfigurationErrorsException.cs
- DataView.cs
- Label.cs
- SoapParser.cs
- MouseEventArgs.cs
- Preprocessor.cs
- ClientSettingsStore.cs
- ActiveDesignSurfaceEvent.cs
- ReadWriteSpinLock.cs
- HwndProxyElementProvider.cs
- handlecollector.cs
- ExceptionUtil.cs
- CursorInteropHelper.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- ImageAnimator.cs
- ping.cs
- PrintEvent.cs
- BinaryKeyIdentifierClause.cs
- MsmqNonTransactedPoisonHandler.cs
- FtpWebResponse.cs
- SqlDataSourceSelectingEventArgs.cs
- ObjectViewEntityCollectionData.cs
- CodeCompiler.cs
- InfoCardAsymmetricCrypto.cs
- WebPartDisplayModeCancelEventArgs.cs
- ConvertEvent.cs
- XmlCharacterData.cs
- TransactionFlowBindingElementImporter.cs
- ResXFileRef.cs
- ContractType.cs
- shaperfactoryquerycacheentry.cs
- ChildrenQuery.cs
- GridViewColumn.cs
- WebPartVerbsEventArgs.cs
- ErasingStroke.cs
- ServiceThrottle.cs
- DataGridViewComboBoxCell.cs
- ListViewItem.cs
- EncoderParameter.cs
- TagMapInfo.cs
- DataStreams.cs
- Assembly.cs
- TableLayoutStyleCollection.cs
- TextSearch.cs
- dsa.cs
- RedirectionProxy.cs
- ComboBoxItem.cs
- MeshGeometry3D.cs
- DataServiceStreamProviderWrapper.cs
- GridViewHeaderRowPresenter.cs
- Pointer.cs
- ForEachAction.cs
- AmbiguousMatchException.cs
- DataGridViewMethods.cs
- DefaultBindingPropertyAttribute.cs
- XmlSchemaException.cs
- MoveSizeWinEventHandler.cs
- DataSourceHelper.cs
- PreviewPageInfo.cs
- DataMisalignedException.cs
- LayoutSettings.cs
- PropertyChangedEventArgs.cs
- HtmlInputSubmit.cs
- PrintDialogException.cs
- KnownBoxes.cs
- UpdatePanel.cs
- SizeAnimationBase.cs
- Int64KeyFrameCollection.cs
- PrintEvent.cs
- AtomicFile.cs
- PenContexts.cs
- X509UI.cs
- FontStyleConverter.cs
- CodeAttachEventStatement.cs
- PointLight.cs
- XmlName.cs
- DataGridRelationshipRow.cs
- QueryContinueDragEventArgs.cs
- ErrorStyle.cs
- LayoutEngine.cs
- OdbcConnectionString.cs
- RealizedColumnsBlock.cs
- _Events.cs
- ColumnResizeAdorner.cs
- ProtocolsConfiguration.cs
- XhtmlBasicLinkAdapter.cs
- MultipartContentParser.cs
- ScriptReference.cs
- HttpListenerPrefixCollection.cs
- InkPresenter.cs
- EventMap.cs
- XmlSchemaComplexContent.cs