使用SHIFT + 滚动以在ScrollViewer UWP中横向滚动

4

我希望能在按住键盘上的 SHIFT 键时,启用滚动条水平滚动 ScrollViewer

我从这里学到了使用 PointerWheelChanged 事件来实现。但由于ScrollViewer 在内部处理该事件,因此我的操作程序永远不会被调用。为了解决这个问题,我使用了 AddHandler 方法,如“路由事件概述”文章所述。

这样做确实有效… 但似乎是在 ScrollViewer 运行其内部代码之后运行我的代码。其结果是 ScrollViewer 的内容先在垂直方向上偏移,然后再在水平方向上偏移。它们看起来是按照这个顺序发生的,并且设置 e.Handled = true 也无法阻止它。

是否有一种方式可以“拦截”滚动事件,以便我可以使用自己的逻辑来处理它,从而允许ScrollViewer在按下 SHIFT 键时进行水平滚动?最近我在这里提出了类似的问题(涉及拦截控件的输入以便使用自己的逻辑来处理它),答案中涉及到处理另一个事件,该事件发生在控件运行其自己的逻辑之前。但我没有看到类似于“预执行”指针滚动事件的事件。

下面是我的代码。请注意,ScrollViewer可以水平和垂直滚动,以及缩放:

<!-- Contained in Grid in a UserControl, if that's relevant -->
<ScrollViewer Name="MyCanvasScrollViewer"
              VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Auto"
              ZoomMode="Enabled"
              ZoomSnapPointsType="Optional"
              PointerWheelChanged="MyCanvasScrollViewer_PointerWheelChanged">
    <!-- Content to pan -->
</ScrollViewer>

代码后台:

// Constructor for the user contol.
public MyControl()
{
    // Add the scroll wheel event handler and force it to run.
    this.MyCanvasScrollViewer.AddHandler(ScrollViewer.PointerWheelChangedEvent, new PointerEventHandler(this.MyCanvasScrollViewer_PointerWheelChanged), true);

    // Other un-related stuff omitted here...
}

// Event handler for the Pointer Wheel Changed event.
private void MyCanvasScrollViewer_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
    // If SHIFT is pressed...
    var keyState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
    if ((keyState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down)
    {
        // Get the amount to scroll.
        PointerPoint pointer = e.GetCurrentPoint(this.WallCanvasScrollViewer);
        double scrollWheelDelta = pointer.Properties.MouseWheelDelta;

        // Change the view in the scroll viewer.
        this.MyCanvasScrollViewer.ChangeView(scrollWheelDelta, null, null, true);

        // Mark event as handled.
        e.Handled = true;
    }
}
1个回答

5

您可以在Shift按下键(keydown)时禁用VerticalScrollMode,并在释放键(keyup)时启用它。不需要使用 pointerwheelchanged 事件本身。这种方法完全可行。

Xaml

<ScrollViewer ZoomMode="Enabled" x:Name="MyScrollViewer"  HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Visible" >
   <Image Height="600" Width="500" Source="/Assets/1.jpg"></Image>
</ScrollViewer>

//C#代码

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        CoreWindow.GetForCurrentThread().KeyDown += MainPage_KeyDown;
        CoreWindow.GetForCurrentThread().KeyUp += MainPage_KeyUp; ;
    }

    private void MainPage_KeyUp(CoreWindow sender, KeyEventArgs args)
    {
        if (args.VirtualKey == VirtualKey.Shift)
        {                
            MyScrollViewer.IsScrollInertiaEnabled = true;
            MyScrollViewer.VerticalScrollMode = ScrollMode.Enabled;
        }
    }

    private void MainPage_KeyDown(CoreWindow sender, KeyEventArgs args)
    {
        if (args.VirtualKey == VirtualKey.Shift)
        {
            MyScrollViewer.IsScrollInertiaEnabled = false;
            MyScrollViewer.VerticalScrollMode = ScrollMode.Disabled;
        }
    }

}

2
那似乎大部分都可以工作。我在ScrollViewer中有很多更大的X和Y内容。虽然按住SHIFT键确实允许水平滚动,但是ScrollViewer在水平滚动之前会先跳转到特定的垂直滚动值...无论我开始水平滚动时垂直值是什么。你有什么想法? - Michael Kintscher they-them
1
进一步检查表明,它跳跃以使内容在“ScrollViewer”中垂直居中。 - Michael Kintscher they-them
3
在按键事件中设置 MyScrollViewer.IsScrollInertiaEnabled = false; 并启用它。跳跃以停止滚动。我已编辑我的答案。 - Vignesh
IsScrollInertiaEnabled = false 设置为false确实解决了垂直捕捉的问题,但当然我们都习惯了流畅的滑动。虽然这不是世界末日,但我想知道是否有办法兼顾两全。 - BCA

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