【问题标题】:SHIFT + Scroll to Scroll Horizontally in ScrollViewer UWPSHIFT + Scroll 在 ScrollViewer UWP 中水平滚动
【发布时间】:2018-12-14 20:29:17
【问题描述】:

我想启用在滚动时按住键盘上的 SHIFT 以水平滚动ScrollViewer

我从here 了解到PointerWheelChanged 事件是我正在寻找的事件。但是,处理它不起作用,因为ScrollViewer 在内部处理它,所以我的处理程序永远不会被调用。为了解决这个问题,我使用了AddHandler 方法,如"Routed Events Overview" 文章中所述。

这可行...但似乎在ScrollViewer运行其内部代码之后运行我的代码。这样做的结果是ScrollViewer 内容先垂直平移,然后再水平平移。它们似乎按此顺序发生,设置 e.Handled = true 并不能阻止它。

有没有办法“拦截”滚动,所以我可以用自己的逻辑处理它,从而允许ScrollViewer 在按下 SHIFT 时水平平移?我最近问了一个类似的问题(涉及拦截对控件的输入,以便我可以用自己的逻辑处理它)here,答案涉及处理不同的事件,该事件发生在控件运行自己的逻辑之前。对于指针滚动,我没有看到类似的“事前发生”事件。

我的代码如下。请注意,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;
    }
}

【问题讨论】:

    标签: c# xaml uwp event-handling scrollviewer


    【解决方案1】:

    您可以简单地在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;
            }
        }
    
    }
    

    【讨论】:

    • 这似乎主要工作。我在 ScrollViewer 中的内容在 X 和 Y 中都大得多。虽然按住 SHIFT 确实允许水平滚动,但 ScrollViewer 在水平滚动之前首先跳转到特定的垂直滚动值......不管我的垂直方向是什么值是我开始水平滚动的时间。想法?
    • 进一步检查表明它的跳跃使得内容在ScrollViewer 中垂直居中。
    • 设置 MyScrollViewer.IsScrollInertiaEnabled = false;按下并启用它。使跳跃停止。我已经编辑了我的答案
    猜你喜欢
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多