Raising WPF MouseLeftButtonDownEvent event programmatically
Asked Answered
C

2

14

I am trying to raise a MouseLeftButtonDownEvent by bubbling it up the Visual tree with the following code.

var args = new MouseButtonEventArgs(Mouse.PrimaryDevice,0,MouseButton.Left);
args.RoutedEvent = UIElement.MouseLeftButtonDownEvent;
args.Source = this;
RaiseEvent(args);

For some reason the higher level components are not receiving this bubbled event. Am I overlooking something or is it not possible to raise this Mouse event

Centro answered 10/3, 2010 at 22:56 Comment(0)
L
27

Your problem is that you are raising an event that does not bubble.

MouseLeftButtonDownEvent is defined as RoutingStrategy.Direct, which means it is routed to only the control receiving the event.

You want to use Mouse.MouseDownEvent event instead. UIElement and other classes internally convert this into a MouseLeftButtonDownEvent. Make sure you set e.ChangedButton to MouseButton.Left:

RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
{
  RoutedEvent = Mouse.MouseDownEvent,
  Source = this,
});
Liv answered 11/3, 2010 at 0:46 Comment(0)
A
0

I might be wrong in my opinion - but at least I looked some time ago for quite some length into InputManager.

My resume from that is: The bubbling and tunneling is done by InputManager. However calling uielement.Raise() will only ever deliver the event directly (regardless of the RoutingStrategy as Ray Burns mentioed).

But (guessing) depending on RoutingStrategy the InputManager goes up and down the visual tree between CompositionRoot and the VisualTreeHlper.Hittest()-ed Visual and delivers tunneling and bublling events.

There is a way to raise Events via the InputManager, but it is not official and needs reflection (I have it from another Stackoverflow post):

    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);
    }
Anglice answered 16/10, 2015 at 7:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.