简体   繁体   中英

WPF - Content inside a ScrollViewer element does not touch-scroll when touching a child DataGrid

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:

  • The Behavior needs to be attached to the outer ScrollViewer .
  • This solution can't handle MultiTouch. If you put two fingers on the touch screen the Events get fired by both fingers and the vertical scroll doesn't work correctly.
  • To get the typical vertical scroll behaviour on the outer ScrollViewer you should change the actualDistance to the original distance as follows:
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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM