以编程方式触发WPF MouseLeftButtonDownEvent事件

14

我正在尝试通过以下代码将MouseLeftButtonDownEvent事件沿着可视树向上传递。

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

不知道为什么更高级别的组件没有接收到这个冒泡事件。 我是否漏看了什么或者不能触发这个鼠标事件?

2个回答

27

您的问题在于您引发了一个不会冒泡的事件。

MouseLeftButtonDownEvent 被定义为 RoutingStrategy.Direct,这意味着它只被路由到接收事件的控件。

您需要使用 Mouse.MouseDownEvent 事件。 UIElement 和其他类内部将其转换为 MouseLeftButtonDownEvent。 确保您将 e.ChangedButton 设置为 MouseButton.Left

RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
{
  RoutedEvent = Mouse.MouseDownEvent,
  Source = this,
});

0

我可能在我的观点上有所错误 - 但至少我曾经花了相当长的时间研究过InputManager

我的结论是:冒泡和隧道是由InputManager完成的。然而,调用uielement.Raise()只会直接传递事件(无论RoutingStrategy如何,正如Ray Burns所提到的)。

但是(猜测)根据RoutingStrategyInputManagerCompositionRoot和通过VisualTreeHlper.Hittest()检测到的可视化树之间上下移动,并传递隧道和冒泡事件。

有一种方法可以通过InputManager引发事件,但这不是官方的,需要反射(我从另一个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);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接