potrei sbagliarmi a mio parere - ma almeno ho guardato un po 'di tempo fa per un po' la lunghezza in InputManager
.
Il mio curriculum è: il bubbling e il tunneling sono eseguiti da InputManager
. Tuttavia chiamando lo uielement.Raise()
consegnerà sempre l'evento direttamente (indipendentemente dallo RoutingStrategy
come Ray Burns mentioed).
Ma (indovinare) a seconda del RoutingStrategy
InputManager
va su e giù l'albero visiva tra CompositionRoot
e VisualTreeHlper.Hittest()-
Ed visiva e fornisce tunneling ed eventi bublling.
C'è un modo per raccogliere eventi tramite l'InputManager, ma non è ufficiale e ha bisogno di riflessione (ce l'ho da un altro post StackOverflow):
void RaiseMouseInputReportEvent(Visual eventSource, int timestamp, int pointX, int pointY, int wheel)
{
Assembly targetAssembly = Assembly.GetAssembly(typeof(InputEventArgs));
Type mouseInputReportType = targetAssembly.GetType("System.Windows.Input.RawMouseInputReport");
Object mouseInputReport = mouseInputReportType.GetConstructors()[0].Invoke(new Object[] {
InputMode.Foreground, timestamp, PresentationSource.FromVisual(eventSource),
RawMouseActions.AbsoluteMove | RawMouseActions.Activate,
pointX, pointY, wheel, IntPtr.Zero });
mouseInputReportType.GetField("_isSynchronize", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(mouseInputReport, true);
InputEventArgs inputReportEventArgs = (InputEventArgs)targetAssembly
.GetType("System.Windows.Input.InputReportEventArgs")
.GetConstructors()[0]
.Invoke(new Object[] {
Mouse.PrimaryDevice,
mouseInputReport });
inputReportEventArgs.RoutedEvent = (RoutedEvent)typeof(InputManager)
.GetField("PreviewInputReportEvent", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
.GetValue(null);
bool handled = InputManager.Current.ProcessInput((InputEventArgs)inputReportEventArgs);
}