With the following XAML:
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="600" Width="640">
<ScrollViewer PanningMode="Both">
<StackPanel>
<TextBlock TextWrapping="Wrap">LOTS OF TEXT...</TextBlock>
<DataGrid MinHeight="200">
<DataGrid.Columns>
<DataGridTextColumn Width="100"></DataGridTextColumn>
<DataGridTextColumn Width="100"></DataGridTextColumn>
<DataGridTextColumn Width="100"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<TextBlock TextWrapping="Wrap">LOTS OF TEXT...</TextBlock>
</StackPanel>
</ScrollViewer>
</Window>
You can scroll by touching on the TextBlock
s. However, if you touch the DataGrid
and attempt to scroll, it does nothing.
I'm guessing it has something to do with the fact that the content in the DataGrid
is potentially scrollable itself so WPF is getting confused with the potentially nested scrollbars.
The desired behaviour is that touching in the DataGrid
will scroll the content inside the DataGrid
first (if necessary). Then, when content in the DataGrid
has been fully scrolled, the main window will scroll.
Similar to PreviewMouseWheel ( Bubbling scroll events from a ListView to its parent ), you can do same with Touch controls:
C#:
public sealed class SubControlsTouchScrollEvent : Behavior<UIElement>
{
double originalDistance;
double actualDistance;
int delta;
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewTouchDown += AssociatedObject_PreviewTouchDown;
AssociatedObject.PreviewTouchMove += AssociatedObject_PreviewTouchMove;
}
protected override void OnDetaching()
{
AssociatedObject.PreviewTouchUp -= AssociatedObject_PreviewTouchDown;
AssociatedObject.PreviewTouchMove -= AssociatedObject_PreviewTouchMove;
base.OnDetaching();
}
void AssociatedObject_PreviewTouchDown(object sender, TouchEventArgs e)
{
System.Windows.IInputElement s = sender as System.Windows.IInputElement;
originalDistance = e.GetTouchPoint(s).Position.Y;
}
void AssociatedObject_PreviewTouchMove(object sender, TouchEventArgs e)
{
ScrollViewer s = sender as ScrollViewer;
actualDistance = e.GetTouchPoint(s).Position.Y;
delta = Convert.ToInt16(actualDistance - originalDistance);
s.ScrollToVerticalOffset(s.VerticalOffset - (delta * 0.1));
e.Handled = true;
}
}
XAML:
<ScrollViewer PanningMode="Both" Background="Transparent">
<interactivity:Interaction.Behaviors>
<local:SubControlsTouchScrollEvent />
</interactivity:Interaction.Behaviors>
</ScrollViewer>
NOTE: This is only for vertical scrolling, but you can add horizontal scrolling in the same way.
The solution from @neo_st worked for me. Three important sidenotes to make this work:
void AssociatedObject_PreviewTouchMove(object sender, TouchEventArgs e)
{
ScrollViewer s = sender as ScrollViewer;
actualDistance = e.GetTouchPoint(s).Position.Y;
delta = Convert.ToInt16(actualDistance - originalDistance);
s.ScrollToVerticalOffset(s.VerticalOffset - delta);
originalDistance = actualDistance;
e.Handled = true;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.