使用以下 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>
您可以通过触摸TextBlock
s来滚动。 但是,如果您触摸DataGrid
并尝试滚动,则它不会执行任何操作。
我猜这与DataGrid
中的内容本身可能是可滚动的这一事实有关,因此 WPF 与潜在的嵌套滚动条混淆。
所需的行为是,触摸DataGrid
将首先滚动DataGrid
内的内容(如有必要)。 然后,当DataGrid
中的内容完全滚动时,主窗口将滚动。
与 PreviewMouseWheel(冒泡滚动事件从 ListView 到其父级)类似,您可以使用触摸控件执行相同的操作:
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>
注意:这仅适用于垂直滚动,但您可以以相同的方式添加水平滚动。
@neo_st的解决方案对我有用。完成这项工作的三个重要旁注:
- 行为需要附加到外部滚动查看器。
- 此解决方案无法处理多点触控。如果您将两根手指放在触摸屏上,则事件会被两根手指触发,垂直滚动无法正常工作。
- 要在外部滚动查看器上获得典型的垂直滚动行为,您应该将实际距离更改为原始距离,如下所示:
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;
}