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. // 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
- SelectionUIService.cs
- RsaElement.cs
- VisualCollection.cs
- InstancePersistenceException.cs
- LayoutEditorPart.cs
- TextAdaptor.cs
- RawKeyboardInputReport.cs
- ACE.cs
- StringSorter.cs
- ReachDocumentSequenceSerializerAsync.cs
- DataGridViewCellFormattingEventArgs.cs
- SortAction.cs
- DuplicateWaitObjectException.cs
- DbConnectionPoolGroup.cs
- XNameTypeConverter.cs
- MultiTrigger.cs
- ProfilePropertyNameValidator.cs
- WsdlImporterElementCollection.cs
- PopupRootAutomationPeer.cs
- Ipv6Element.cs
- SettingsPropertyNotFoundException.cs
- BrowserDefinition.cs
- TextSchema.cs
- ChangePassword.cs
- SByteStorage.cs
- SqlConnection.cs
- DependencyPropertyConverter.cs
- FixedSOMPage.cs
- ArcSegment.cs
- UseAttributeSetsAction.cs
- RoutingChannelExtension.cs
- Function.cs
- LayoutUtils.cs
- RegistryPermission.cs
- ObjectStateFormatter.cs
- MouseActionConverter.cs
- ConfigXmlWhitespace.cs
- Misc.cs
- XmlSchemaImport.cs
- RetrieveVirtualItemEventArgs.cs
- ScriptModule.cs
- TemplateControl.cs
- ExtenderControl.cs
- TableParaClient.cs
- ContentType.cs
- CreateParams.cs
- DataSourceView.cs
- AuthorizationRule.cs
- Double.cs
- AutomationProperty.cs
- ConstraintConverter.cs
- MediaPlayer.cs
- SelectionHighlightInfo.cs
- HostingEnvironmentSection.cs
- Serializer.cs
- ScriptHandlerFactory.cs
- CultureInfoConverter.cs
- SafeFileHandle.cs
- TimestampInformation.cs
- RenderDataDrawingContext.cs
- RIPEMD160Managed.cs
- XmlAttributeAttribute.cs
- DbConnectionPoolGroup.cs
- FontConverter.cs
- EpmContentSerializerBase.cs
- DBSchemaRow.cs
- SecurityManager.cs
- ChangesetResponse.cs
- BasicViewGenerator.cs
- HttpRequestWrapper.cs
- TracedNativeMethods.cs
- AtomMaterializer.cs
- LocalizationParserHooks.cs
- GrammarBuilderDictation.cs
- CodeRegionDirective.cs
- SqlDataSourceQueryConverter.cs
- Marshal.cs
- IndentTextWriter.cs
- UserPersonalizationStateInfo.cs
- ExpressionConverter.cs
- StylusPointPropertyUnit.cs
- CannotUnloadAppDomainException.cs
- TextBoxRenderer.cs
- ToolStripManager.cs
- WebRequestModuleElement.cs
- XmlSchemaSimpleType.cs
- IdentityNotMappedException.cs
- AuthorizationRule.cs
- x509utils.cs
- ToolBarButton.cs
- PageSetupDialog.cs
- WsatEtwTraceListener.cs
- TextTreeExtractElementUndoUnit.cs
- SerializerDescriptor.cs
- HttpCacheVary.cs
- AmbientLight.cs
- ConnectionPoint.cs
- FormsAuthenticationConfiguration.cs
- EventProperty.cs
- LogSwitch.cs