Reputation: 825
I would like to enable holding down SHIFT on the keyboard while scrolling to scroll a ScrollViewer
horizontally.
I learned from here that the PointerWheelChanged
event is the one I am looking for. Handling that, however, doesn't work because the ScrollViewer
handles it internally, so my handler is never called. To get around that, I used the AddHandler
method, as described in the "Routed Events Overview" article.
This works... but appears to be running my code AFTER the ScrollViewer
runs its internal code. The result of this is that the ScrollViewer
content pans vertically, then horizontally. They appear to happen in that order, and setting e.Handled = true
doesnt stop it.
Is there a way to "intercept" the scroll, so I can handle it with my own logic, thus allowing the ScrollViewer
to pan horizontally if SHIFT is pressed? I recently asked a similar question (involving intercepting input to a control so I could handle it with my own logic) here, where the answer involved handling a different event, where that event took place prior to control running its own logic. I do not see a similar "pre stuff happening" event for the pointer scroll.
The code I have follows. Note that the ScrollViewer
can scroll BOTH horizontally and vertically, as well as zoom:
<!-- 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>
Code-behind:
// 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;
}
}
Upvotes: 4
Views: 1314
Reputation: 1882
You could simply disable VerticalScrollMode
in shift
keydown and enable it on keyup. No need for pointerwheelchanged
itself. It works perfectly fine.
Xaml
<ScrollViewer ZoomMode="Enabled" x:Name="MyScrollViewer" HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Visible" >
<Image Height="600" Width="500" Source="/Assets/1.jpg"></Image>
</ScrollViewer>
//C# code
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;
}
}
}
Upvotes: 5