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
- CreateUserErrorEventArgs.cs
- APCustomTypeDescriptor.cs
- ObjectItemAssemblyLoader.cs
- DataSourceXmlClassAttribute.cs
- MatchingStyle.cs
- FontSourceCollection.cs
- IdentityManager.cs
- Graphics.cs
- MSAAEventDispatcher.cs
- SByteStorage.cs
- FixedFindEngine.cs
- LineProperties.cs
- SessionEndingEventArgs.cs
- SqlDataSource.cs
- cookiecollection.cs
- DataList.cs
- NameHandler.cs
- ReaderWriterLock.cs
- DigitalSignature.cs
- WorkflowApplicationTerminatedException.cs
- PageAsyncTaskManager.cs
- VSWCFServiceContractGenerator.cs
- DataGridViewLayoutData.cs
- ResourceManager.cs
- WebPartZone.cs
- EntityRecordInfo.cs
- ImageFormat.cs
- PageAsyncTask.cs
- ExpressionTextBox.xaml.cs
- FixedSOMTableRow.cs
- PropertiesTab.cs
- MutexSecurity.cs
- XmlNodeChangedEventArgs.cs
- ScrollChangedEventArgs.cs
- WebPartDisplayMode.cs
- SettingsPropertyIsReadOnlyException.cs
- CacheChildrenQuery.cs
- ServiceProviders.cs
- ProgressBarRenderer.cs
- OptimalBreakSession.cs
- FamilyMapCollection.cs
- Recipient.cs
- ManagementPath.cs
- HiddenFieldPageStatePersister.cs
- SymDocumentType.cs
- DataSourceUtil.cs
- CqlLexerHelpers.cs
- ScaleTransform3D.cs
- ImmComposition.cs
- LayoutEditorPart.cs
- DependencyProperty.cs
- DataKey.cs
- ExpressionBuilderContext.cs
- TextEffectResolver.cs
- TypeConverter.cs
- BackgroundFormatInfo.cs
- TextChangedEventArgs.cs
- MiniCustomAttributeInfo.cs
- ServiceAuthorizationManager.cs
- RectangleGeometry.cs
- FunctionImportMapping.cs
- LayoutEngine.cs
- NativeMethods.cs
- MiniModule.cs
- DrawingAttributeSerializer.cs
- DataGridTableCollection.cs
- ZoneIdentityPermission.cs
- PageRouteHandler.cs
- DodSequenceMerge.cs
- FontFamilyIdentifier.cs
- SafeNativeMethods.cs
- NTAccount.cs
- SettingsAttributeDictionary.cs
- DataContractSerializerElement.cs
- XsdCachingReader.cs
- AssemblyCollection.cs
- CheckoutException.cs
- ZipIOExtraFieldZip64Element.cs
- EntitySqlQueryCacheEntry.cs
- HttpConfigurationSystem.cs
- AudioLevelUpdatedEventArgs.cs
- BrowsableAttribute.cs
- DBSqlParserColumn.cs
- DSASignatureFormatter.cs
- ContextQuery.cs
- SplitContainer.cs
- DbParameterCollectionHelper.cs
- SqlCommandSet.cs
- OpCodes.cs
- Geometry.cs
- XmlSerializationReader.cs
- XmlSequenceWriter.cs
- CalendarDay.cs
- AuthenticationException.cs
- TrackingRecordPreFilter.cs
- AssemblyLoader.cs
- TableLayoutSettings.cs
- SymmetricAlgorithm.cs
- XslAstAnalyzer.cs
- UserControlCodeDomTreeGenerator.cs