ScrollViewer and handling manipulation events on c

2019-01-18 00:48发布

I have created a Windows 8 Store App using C# / XAML. My interface includes a scrollable list, which is rendered using an ScrollViewer. I would like to be able to handle manipulation events on the elements within the list, however, setting ManipulationMode to anything other than None on the list element causes my list to no longer scroll.

Here is a simplified version of the UI:

<ScrollViewer>
  <Border/> <!-- these contain child content -->
  <Border/>
  <Border/>
  <!-- Set ManipulationMode on an element in order to receive manipulation events -->
  <!-- This causes the scroll viewer to stop working! -->
  <Border ManipulationMode="All"
          ManipulationDelta="..."/>
  <Border/>
  <Border/>
</ScrollViewer>

I understand that the WinRT ScrollViewer uses a special ManipulationMode of System for performance reasons, but I would like to have a vertically scrolling list, containing elements that respond to horizontal manipulation / gestures. Can anyone think of a creative workaround that would make this possible?

2条回答
冷血范
2楼-- · 2019-01-18 01:03

What I have done was I put a transparent rectangle on top of the ScrollViewer and handle manipulations there. When I find the manipulation should scroll the ScrollViewer - I scroll the ScrollViewer using the ScrollToHorizontal/VerticalOffset() methods. On ManipulationStarted I also use VisualTreeHelper.FindElementsInHostCoordinates to check which item I could manipulate too and then I can decide whether to manipulate that item or not depending on various conditions. It's quite a bit of custom code though. You would also need to update the RenderTransform of the ScrollContentPresenter in the ScrollViewer when the user tries to drag farther than minimum/maximum offset to immitate the ScrollViewer default behavior, handle mouse scrollwheel etc. Nothing YOU could not handle of course. I could not find a better way unfortunately and I am interested if someone finds one.

EDIT* Another solution I thought of when trying to answer another similar question was to use another ScrollViewer as a child item and use its ViewChanged events instead of manipulation events.

EDIT 2*

Also with Windows 8.1 you get ManipulationModes.System which combined with other modes should allow you to handle manipulations inside of a ScrollViewer. Then you can call CancelDirectManipulations() on the manipulated element once you want its parent ScrollViewers to stop processing manipulations for pan&zoom.

查看更多
我想做一个坏孩纸
3楼-- · 2019-01-18 01:18

it may be long time but didn't find any good solution. I just achieved what I wanted very easily.

public MovableGrid()
        {
            ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.System;
            AddHandler(ManipulationDeltaEvent, new ManipulationDeltaEventHandler(UIElement_OnManipulationDelta), true);
            AddHandler(ManipulationCompletedEvent, new ManipulationCompletedEventHandler(UIElement_OnManipulationCompleted), true);
        }

I wanted my MovableGrid to be moved on X axis and I have list of MovableGrids which I wanted to be scrolled with scrollviewer. That's enough to do that.

查看更多
登录 后发表回答