Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / DescendentsWalker.cs / 2 / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CompiledRegexRunner.cs
- OciEnlistContext.cs
- CompressStream.cs
- MTConfigUtil.cs
- CollectionView.cs
- MinimizableAttributeTypeConverter.cs
- XmlTextReader.cs
- ProtocolProfile.cs
- VSWCFServiceContractGenerator.cs
- RequestQueryParser.cs
- ListBindingConverter.cs
- TrackBar.cs
- Region.cs
- mediapermission.cs
- XmlCustomFormatter.cs
- XmlMembersMapping.cs
- InternalRelationshipCollection.cs
- SqlSupersetValidator.cs
- IntPtr.cs
- RoleManagerSection.cs
- Rfc2898DeriveBytes.cs
- TreeNodeClickEventArgs.cs
- EventLogPermission.cs
- TimeSpanStorage.cs
- GridViewColumn.cs
- GeneratedCodeAttribute.cs
- TraceListeners.cs
- mediapermission.cs
- StringAnimationBase.cs
- HtmlProps.cs
- DataFieldEditor.cs
- XsdCachingReader.cs
- FieldToken.cs
- XslTransform.cs
- FigureParaClient.cs
- EqualityComparer.cs
- SaveRecipientRequest.cs
- Compensate.cs
- FloaterParagraph.cs
- ObjectDataProvider.cs
- MeasureData.cs
- UriWriter.cs
- ToolStripSeparatorRenderEventArgs.cs
- Sql8ExpressionRewriter.cs
- MailMessage.cs
- ContentAlignmentEditor.cs
- RadioButtonList.cs
- OleDbRowUpdatedEvent.cs
- Encoding.cs
- TemplatingOptionsDialog.cs
- ImageSource.cs
- TrackingDataItem.cs
- StaticContext.cs
- _ConnectStream.cs
- TCEAdapterGenerator.cs
- OdbcConnectionPoolProviderInfo.cs
- StoreContentChangedEventArgs.cs
- MenuAutomationPeer.cs
- TextServicesManager.cs
- LocalFileSettingsProvider.cs
- DragCompletedEventArgs.cs
- AbstractDataSvcMapFileLoader.cs
- UIElement3DAutomationPeer.cs
- StateChangeEvent.cs
- Ref.cs
- MenuItemBindingCollection.cs
- Underline.cs
- ControlOperationBehavior.cs
- XsdBuilder.cs
- SerializationSectionGroup.cs
- MaskInputRejectedEventArgs.cs
- HtmlElementEventArgs.cs
- Track.cs
- DefaultValueAttribute.cs
- EventTask.cs
- TransactionOptions.cs
- AnnotationMap.cs
- autovalidator.cs
- HttpResponse.cs
- PropertyKey.cs
- CodeParameterDeclarationExpression.cs
- DiscoveryRequestHandler.cs
- VScrollProperties.cs
- DecoderReplacementFallback.cs
- ExtendedPropertyDescriptor.cs
- Models.cs
- OperationResponse.cs
- DragEventArgs.cs
- SinglePageViewer.cs
- XsltException.cs
- CultureInfo.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- Soap.cs
- XmlSignatureProperties.cs
- ServiceDocument.cs
- odbcmetadatacollectionnames.cs
- ResXBuildProvider.cs
- RegexEditorDialog.cs
- Floater.cs
- ReadOnlyNameValueCollection.cs