// Add a preopportunity handler for the logical parent incase of templated element. internal static void AddParentPreOpportunityHandler(DependencyObject o, EventRoute route, RoutedEventArgs args) { // If the logical parent is different from visual parent then add handler on behalf of the // parent into the route. This is to cover the templated elements, where event could be // handled by one of the child visual element but we should consider it as if event is handled by // parent element ( logical parent). DependencyObject visualParent = null; if (o is Visual || o is Visual3D) { visualParent = UIElementHelper.GetUIParent(o); } DependencyObject logicalParent = SynchronizedInputHelper.GetUIParentCore(o); if (logicalParent != null && logicalParent != visualParent) { UIElement e = logicalParent as UIElement; if (e != null) { e.AddSynchronizedInputPreOpportunityHandler(route, args); } else { ContentElement ce = logicalParent as ContentElement; if (ce != null) { ce.AddSynchronizedInputPreOpportunityHandler(route, args); } else { UIElement3D e3D = logicalParent as UIElement3D; if (e3D != null) { e3D.AddSynchronizedInputPreOpportunityHandler(route, args); } } } } }