问题
I have an app in wpf using caliburn micro framework with mvvm pattern which is running in kiosk with touch screen. i want to scroll buttons and when the user wants to click them. I have made grid scrollable inside a scroll viewer but the proplem is that when I leave the touch, it's raising the button-click event. Here's the code (xaml) :
<ScrollViewer VerticalScrollBarVisibility="Hidden" x:Name="scroller">
<Grid ScrollViewer.CanContentScroll="True">
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row1"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row2"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row3"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row4"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row5"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row6"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row7"/>
<RowDefinition Height="15"/>
<RowDefinition x:Name="Row8"/>
</Grid.RowDefinitions>
<Button x:Name="ViewRedirect1" Grid.Row="1">
<Image Source="{Binding Path=LeftImage1}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect2" Grid.Row="3">
<Image Source="{Binding Path=LeftImage2}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect3" Grid.Row="5">
<Image Source="{Binding Path=LeftImage3}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect4" Grid.Row="7">
<Image Source="{Binding Path=LeftImage4}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect5" Grid.Row="9">
<Image Source="{Binding Path=LeftImage5}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect6" Grid.Row="11">
<Image Source="{Binding Path=LeftImage6}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect7" Grid.Row="13">
<Image Source="{Binding Path=LeftImage7}" Stretch="UniformToFill"/>
</Button>
<Button x:Name="ViewRedirect8" Grid.Row="15">
<Image Source="{Binding Path=LeftImage8}" Stretch="UniformToFill"/>
</Button>
</Grid>
</ScrollViewer>
and here is the behind code about the events
private Point scrollStartPoint;
private Point scrollStartOffset;
private DateTime mouseTimer;
private void Scroller_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
mouseTimer = DateTime.Now;
ScrollViewer scrollViewer = sender as ScrollViewer;
if (scrollViewer.IsMouseOver)
{
scrollStartPoint = e.GetPosition(scrollViewer);
scrollStartOffset.X = scrollViewer.HorizontalOffset;
scrollStartOffset.Y = scrollViewer.VerticalOffset;
}
}
private void Scroller_PreviewMouseMove(object sender, MouseEventArgs e)
{
ScrollViewer scrollViewer = sender as ScrollViewer;
if (scrollViewer.IsMouseOver)
{
Point currentPoint = e.GetPosition(scrollViewer);
Point delta = new Point(scrollStartPoint.X - currentPoint.X,
scrollStartPoint.Y - currentPoint.Y);
scrollTarget.X = scrollStartOffset.X + delta.X;
scrollTarget.Y = scrollStartOffset.Y + delta.Y;
scrollViewer.ScrollToHorizontalOffset(scrollTarget.X);
scrollViewer.ScrollToVerticalOffset(scrollTarget.Y);
}
}
private void Scroller_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
ScrollViewer scrollViewer = sender as ScrollViewer;
if (scrollViewer.IsMouseCaptured) {
scrollViewer.ReleaseMouseCapture();
}
TimeSpan difference = DateTime.Now - mouseTimer;
if (difference.TotalMilliseconds>500)
{
e.Handled = true;
}
}
the scroll is goog but when in the button that I leave the finger up, this makes the redirecting
updated code based on answer below
回答1:
You can implement various solutions for this problem,
Look at my answer here, or the authors answer for two separate ways to do it,
WPF Click Button Scrollviewer
The solution is with a left mouse click button, but can be adapted for touch,
my way was to use DateTime, to calculate how much time you press, if you are just touching a button, then it would be less than 1second touch, if you are scrolling it would be more than 1 second, so it doesn't raise the button click event
private DateTime mouseTimer;
private void Scroller_PreviewTouchDown(object sender, TouchEventArgs e)
{
mouseTimer = DateTime.Now;
ScrollViewer scrollViewer = sender as ScrollViewer;
if (scrollViewer.IsMouseOver)
{
scrollStartPoint = e.GetTouchPoint(scrollViewer).Position;
scrollStartOffset.X = scrollViewer.HorizontalOffset;
scrollStartOffset.Y = scrollViewer.VerticalOffset;
}
}
private void Scroller_PreviewTouchUp(object sender, TouchEventArgs e)
{
ScrollViewer scrollViewer = sender as ScrollViewer;
if(scrollViewer.IsMouseCaptured)
{
scrollViewer.ReleaseAllTouchCaptures();
}
TimeSpan difference = DateTime.Now - mouseTimer;
if (difference.TotalSeconds < 1)
{
btn_Click(sender, e); //button you want or don't want to rise event
}
else
return;
}
UPDATE
Second solution, go to the answer I posted above and use the c# code in the second answer, it is more robust
来源:https://stackoverflow.com/questions/40908038/scroll-grid-with-buttons-how-to-prevent-button-elements-from-firing-while-scrol