internal bool BuildRouteCoreHelper(EventRoute route, RoutedEventArgs args, bool shouldAddIntermediateElementsToRoute) { bool flag = false; DependencyObject parent = VisualTreeHelper.GetParent((DependencyObject) this); DependencyObject uiParentCore = this.GetUIParentCore(); DependencyObject dependencyObject = route.PeekBranchNode() as DependencyObject; if (dependencyObject != null && this.IsLogicalDescendent(dependencyObject)) { args.Source = route.PeekBranchSource(); this.AdjustBranchSource(args); route.AddSource(args.Source); route.PopBranchNode(); if (shouldAddIntermediateElementsToRoute) FrameworkElement.AddIntermediateElementsToRoute((DependencyObject) this, route, args, LogicalTreeHelper.GetParent(dependencyObject)); } if (!this.IgnoreModelParentBuildRoute(args)) { if (parent == null) flag = uiParentCore != null; else if (uiParentCore != null) { Visual visual = parent as Visual; if (visual != null) { if (visual.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) flag = true; } else if (((Visual3D) parent).CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) flag = true; route.PushBranchNode((object) this, args.Source); args.Source = (object) parent; } } return flag; }
/// <summary> /// Allows FrameworkElement to augment the /// <see cref="EventRoute"/> /// </summary> /// <remarks> /// NOTE: If this instance does not have a /// visualParent but has a model parent /// then route is built through the model /// parent /// </remarks> /// <param name="route"> /// The <see cref="EventRoute"/> to be /// augmented /// </param> /// <param name="args"> /// <see cref="RoutedEventArgs"/> for the /// RoutedEvent to be raised post building /// the route /// </param> /// <returns> /// Whether or not the route should continue past the visual tree. /// If this is true, and there are no more visual parents, the route /// building code will call the GetUIParentCore method to find the /// next non-visual parent. /// </returns> internal override sealed bool BuildRouteCore(EventRoute route, RoutedEventArgs args) { bool continuePastCoreTree = false; // Verify Context Access // VerifyAccess(); DependencyObject visualParent = (DependencyObject) ContentOperations.GetParent(this); DependencyObject modelParent = this._parent; // FrameworkElement extends the basic event routing strategy by // introducing the concept of a logical tree. When an event // passes through an element in a logical tree, the source of // the event needs to change to the leaf-most node in the same // logical tree that is in the route. // Check the route to see if we are returning into a logical tree // that we left before. If so, restore the source of the event to // be the source that it was when we left the logical tree. DependencyObject branchNode = route.PeekBranchNode() as DependencyObject; if (branchNode != null && IsLogicalDescendent(branchNode)) { // We keep the most recent source in the event args. Note that // this is only for our consumption. Once the event is raised, // it will use the source information in the route. args.Source = (route.PeekBranchSource()); AdjustBranchSource(args); route.AddSource(args.Source); // By popping the branch node we will also be setting the source // in the event route. route.PopBranchNode(); // Add intermediate ContentElements to the route FrameworkElement.AddIntermediateElementsToRoute(this, route, args, LogicalTreeHelper.GetParent(branchNode)); } // Check if the next element in the route is in a different // logical tree. if (!IgnoreModelParentBuildRoute(args)) { // If there is no visual parent, route via the model tree. if (visualParent == null) { continuePastCoreTree = modelParent != null; } else if(modelParent != null) { // If there is a model parent, record the branch node. route.PushBranchNode(this, args.Source); // The source is going to be the visual parent, which // could live in a different logical tree. args.Source = (visualParent); } } return continuePastCoreTree; }
internal static void BuildRouteHelper(DependencyObject e, EventRoute route, RoutedEventArgs args) { if (route == null) { throw new ArgumentNullException("route"); } if (args == null) { throw new ArgumentNullException("args"); } if (args.Source == null) { throw new ArgumentException(SR.Get(SRID.SourceNotSet)); } if (args.RoutedEvent != route.RoutedEvent) { throw new ArgumentException(SR.Get(SRID.Mismatched_RoutedEvent)); } // Route via visual tree if (args.RoutedEvent.RoutingStrategy == RoutingStrategy.Direct) { UIElement uiElement = e as UIElement; ContentElement contentElement = null; UIElement3D uiElement3D = null; if (uiElement == null) { contentElement = e as ContentElement; if (contentElement == null) { uiElement3D = e as UIElement3D; } } // Add this element to route if (uiElement != null) { uiElement.AddToEventRoute(route, args); } else if (contentElement != null) { contentElement.AddToEventRoute(route, args); } else if (uiElement3D != null) { uiElement3D.AddToEventRoute(route, args); } } else { int cElements = 0; while (e != null) { UIElement uiElement = e as UIElement; ContentElement contentElement = null; UIElement3D uiElement3D = null; if (uiElement == null) { contentElement = e as ContentElement; if (contentElement == null) { uiElement3D = e as UIElement3D; } } // Protect against infinite loops by limiting the number of elements // that we will process. if (cElements++ > MAX_ELEMENTS_IN_ROUTE) { throw new InvalidOperationException(SR.Get(SRID.TreeLoop)); } // Allow the element to adjust source object newSource = null; if (uiElement != null) { newSource = uiElement.AdjustEventSource(args); } else if (contentElement != null) { newSource = contentElement.AdjustEventSource(args); } else if (uiElement3D != null) { newSource = uiElement3D.AdjustEventSource(args); } // Add changed source information to the route if (newSource != null) { route.AddSource(newSource); } // Invoke BuildRouteCore bool continuePastVisualTree = false; if (uiElement != null) { //Add a Synchronized input pre-opportunity handler just before the class and instance handlers uiElement.AddSynchronizedInputPreOpportunityHandler(route, args); continuePastVisualTree = uiElement.BuildRouteCore(route, args); // Add this element to route uiElement.AddToEventRoute(route, args); //Add a Synchronized input post-opportunity handler just after class and instance handlers uiElement.AddSynchronizedInputPostOpportunityHandler(route, args); // Get element's visual parent e = uiElement.GetUIParent(continuePastVisualTree); } else if (contentElement != null) { //Add a Synchronized input pre-opportunity handler just before the class and instance handlers contentElement.AddSynchronizedInputPreOpportunityHandler(route, args); continuePastVisualTree = contentElement.BuildRouteCore(route, args); // Add this element to route contentElement.AddToEventRoute(route, args); //Add a Synchronized input post-opportunity handler just after the class and instance handlers contentElement.AddSynchronizedInputPostOpportunityHandler(route, args); // Get element's visual parent e = (DependencyObject)contentElement.GetUIParent(continuePastVisualTree); } else if (uiElement3D != null) { //Add a Synchronized input pre-opportunity handler just before the class and instance handlers uiElement3D.AddSynchronizedInputPreOpportunityHandler(route, args); continuePastVisualTree = uiElement3D.BuildRouteCore(route, args); // Add this element to route uiElement3D.AddToEventRoute(route, args); //Add a Synchronized input post-opportunity handler just after the class and instance handlers uiElement3D.AddSynchronizedInputPostOpportunityHandler(route, args); // Get element's visual parent e = uiElement3D.GetUIParent(continuePastVisualTree); } // If the BuildRouteCore implementation changed the // args.Source to the route parent, respect it in // the actual route. if (e == args.Source) { route.AddSource(e); } } } }