2

I have a WPF application and over a part of it I had a card which displayed Javascript. My problem was that I wasn't able to scroll with the mouse over the Javascript card, because it was swallowing the events. I solved that by hooking into the PreviewMouseWheel event (described here) sent by UIElement:

protected void AddListeners(BorderedCanvas borderedCanvas)
{
    borderedCanvas.PreviewMouseWheel += PreviewMouseWheel;
}

protected void RemoveListeners(BorderedCanvas borderedCanvas)
{
    borderedCanvas.PreviewMouseWheel -= PreviewMouseWheel;
}

protected static void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    if (!e.Handled)
    {
        e.Handled = true;

        var eventArg =
            new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
            {
                RoutedEvent = UIElement.MouseWheelEvent,
                Source = sender
            };

        var parent = VisualTreeHelper.GetParent((UIElement)sender) as UIElement;
        parent?.RaiseEvent(eventArg);
    }
}

Now, scrolling with the mouse works perfectly fine.

However, scrolling with touch doesn't work.

So, I modified AddListeners:

    protected void AddListeners(BorderedCanvas borderedCanvas)
    {
        borderedCanvas.PreviewMouseWheel += PreviewMouseWheel;
        borderedCanvas.PreviewTouchDown += new EventHandler<TouchEventArgs>(OnTouchDown);
        borderedCanvas.PreviewTouchMove += new EventHandler<TouchEventArgs>(OnTouchMove);
    }

And I added these methods:

    protected static void OnTouchDown(object sender, TouchEventArgs e)
    {
        if (!e.Handled)
        {
            e.Handled = true;

            var eventArg =
                new TouchEventArgs(e.TouchDevice, e.Timestamp)
                {
                    RoutedEvent = UIElement.TouchDownEvent,
                    Source = sender
                };

            var parent = VisualTreeHelper.GetParent((UIElement)sender) as UIElement;
            parent?.RaiseEvent(eventArg);
        }
    }

    protected static void OnTouchMove(object sender, TouchEventArgs e)
    {
        if (!e.Handled)
        {
            e.Handled = true;

            var eventArg =
                new TouchEventArgs(e.TouchDevice, e.Timestamp)
                {
                    RoutedEvent = UIElement.TouchMoveEvent,
                    Source = sender
                };

            var parent = VisualTreeHelper.GetParent((UIElement)sender) as UIElement;
            parent?.RaiseEvent(eventArg);
        }
    }

However, scrolling with touch still doesn't work.

Any idea what I did wrong?

To me it seems that I treated the mouse scroll and the touch scroll in a similar way, but the first works and the second doesn't.

bsky
  • 19,326
  • 49
  • 155
  • 270
  • Why are you capturing these events and again manually raising the event for Parent control. Events will be bubbled automatically to parent UI control if you don't handle it (`e.handled = true`). – Swamy Jun 12 '18 at 07:33
  • I tried just setting `e.handled = true` but scrolling didn't work in that case. So I bubbled the event to the parent, as described here https://stackoverflow.com/questions/1585462/bubbling-scroll-events-from-a-listview-to-its-parent and that worked. – bsky Jun 12 '18 at 07:56

1 Answers1

1

You need to set the ScrollViewer.PanningMode for it to work with the touch.

<ScrollViewer PanningMode="Both"/>

The default value for the PanningMode is None.

Raviraj Palvankar
  • 879
  • 1
  • 5
  • 9
  • I don't have some `.xml` file associated with this component, so I'm not sure where to set the `PanningMode` property. – bsky Jun 12 '18 at 07:50
  • You said you have a WPF application, what are your views? Not .xaml? Not even the hosts? – Raviraj Palvankar Jun 12 '18 at 08:02
  • I'm using this library that converts React Native code to WPF: https://github.com/Microsoft/react-native-windows. The views are inside it. This component that I am writing is just a wrapper around the library that should make sure scrolling works. – bsky Jun 12 '18 at 08:05
  • Also, from what I read in the docs, `PanningMode` determines the direction of scrolling. However, scrolling with mouse already works, so probably the direction of scrolling is correct. Therefore, I don't see what the improvement would be if I were to add it. – bsky Jun 12 '18 at 08:32
  • 1
    It enables the scrolling for touch as far as I know from my experience, had faced this issue once, and it did solve it. – Raviraj Palvankar Jun 12 '18 at 08:59
  • Sorry to diverge, but do you have any idea why `PreviewMouseWheel` is passed as a callback directly, while `OnTouchDown` and `OnTouchMove` are wrapped in `EventHandler` ? – bsky Jun 12 '18 at 09:41
  • 1
    I don't think there is any difference in them. You can pass OnTouchDown as a callback directly too as long as it has the argument parameter type as TouchEventArgs. – Raviraj Palvankar Jun 12 '18 at 10:21