I'm finding that when I tap the ScrollViewer, the PointerPressed and PointerExited events fires as expected. But, if I scroll in any direction after touching the screen and lift my finger, no event fires except for PointerCaptureLost which prematurely fires as soon as I scroll.
When I capture the pointer ID and poll the status of the PointerPoint with a timer, the IsInContact flag remains true, even after I lift my finger after scrolling. It works as expected when I simply tap the screen.
ManipulationCompleted has the same effect as above, and I cannot use the ViewChanged event since this fires before I lift my finger.
Is this a bug or am I missing something here? Is there another way I can detect when a user has lifted their finger off the screen? This is driving me bananas.
Sample code below. You'll need to use the simulator in touch-mode or have a touch capable screen to test:
Code:
using System;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace App1
{
public sealed partial class MainPage : Page
{
private readonly DispatcherTimer pointerTimer = new DispatcherTimer();
private uint? CurrentPointerID; //container for the current pointer id when user makes contact with the screeen
public MainPage()
{
this.InitializeComponent();
scrollviewer.PointerPressed += scrollviewer_PointerPressed;
scrollviewer.PointerMoved += scrollviewer_PointerMoved;
scrollviewer.PointerExited += scrollviewer_PointerExited;
scrollviewer.PointerReleased += scrollviewer_PointerReleased;
scrollviewer.PointerCaptureLost += scrollviewer_PointerCaptureLost;
scrollviewer.PointerCanceled += scrollviewer_PointerCanceled;
pointerTimer.Tick += pointerTimer_Tick;
pointerTimer.Interval = TimeSpan.FromMilliseconds(300);
pointerTimer.Start();
}
#region ScrollViewer Events
void scrollviewer_PointerMoved(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Moved";
}
void scrollviewer_PointerExited(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Exited";
}
void scrollviewer_PointerPressed(object sender, PointerRoutedEventArgs e)
{
CurrentPointerID = e.Pointer.PointerId;
EventCalledTextBlock.Text = "Pointer Pressed";
}
void scrollviewer_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Canceled";
}
void scrollviewer_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Capture Lost";
}
void scrollviewer_PointerReleased(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Released";
}
#endregion
void pointerTimer_Tick(object sender, object e)
{
if (!CurrentPointerID.HasValue)
{
PollingTextBlock.Text = string.Empty;
return;
}
try
{
var pointerPoint = PointerPoint.GetCurrentPoint(CurrentPointerID.Value);
PollingTextBlock.Text = pointerPoint.IsInContact ? "Is In Contact" : "Not in Contact";
}
catch (Exception ex)
{
//This exception is raised when the user lifts finger without dragging.
//assume finger is not in contact with screen
PollingTextBlock.Text = "Not in Contact";
}
}
}
}
XAML:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="113*"/>
<RowDefinition Height="655*"/>
</Grid.RowDefinitions>
<ScrollViewer x:Name="scrollviewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible" Grid.Row="1" >
<Rectangle Fill="#FF3783CF" Height="100" Stroke="#FF33D851" Width="{Binding ElementName=grid, Path=ActualWidth}" Margin="100" StrokeThickness="4" />
</ScrollViewer>
<StackPanel Orientation="Vertical" Margin="45,25,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Event Called:" VerticalAlignment="Top" FontSize="24" Margin="0,0,20,0"/>
<TextBlock x:Name="EventCalledTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="24"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Polling Value:" VerticalAlignment="Top" FontSize="24" Margin="0,0,20,0"/>
<TextBlock x:Name="PollingTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="24"/>
</StackPanel>
</StackPanel>
</Grid>
</Page>
I stumbled upon this question since I was struggling with a similar problem. I have a ScrollViewer which has several images in it and I wanted to know what images are shown at the moment the ScrollViewer stops moving...
In the end I did used the ScrollViewer.ViewChanged event. This event keeps triggering untill it has finished with scrolling.
I actually am only interested in the last of these events, but since there is no event that triggers only on that particular moment I need to respond to this one and check for myself if this is the appropriate moment to take actions.
I hope this helps.
ScrollViewer.ViewChanged event: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.scrollviewer.viewchanged?f=255&MSPPError=-2147217396
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With