winui-3winuiwinui-xaml

How to unify ScrollViewer Scroll across two columns in Touch machines?


In extension to this question How to unify ScrollViewer Scroll across two columns?

I have implemented this correctly. For mouse scroll events and trackpad scroll events the gridview_pointerwheelchanged event is invoked, but for touch screens this is not getting invoked. Is there any event to capture the touch screen scroll event as well?

private void Grid_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
    VerticalScrollBar.Value = Math.Max(0, Math.Min(this.VerticalScrollBar.Maximum, this.VerticalScrollBar.Value - e.GetCurrentPoint(this).Properties.MouseWheelDelta));
}

Solution

  • Check this doc about touch interactions. The following seems to work. Can you give it a try?

    <Grid ColumnDefinitions="*,Auto">
        <Grid
            Grid.Column="0"
            ColumnDefinitions="*,*"
            ManipulationDelta="Grid_ManipulationDelta"
            ManipulationMode="All"
            PointerWheelChanged="Grid_PointerWheelChanged"
            SizeChanged="Grid_SizeChanged">
            <Grid.Resources>
                <Style BasedOn="{StaticResource DefaultScrollViewerStyle}" TargetType="ScrollViewer">
                    <Setter Property="VerticalAlignment" Value="Top" />
                    <Setter Property="HorizontalScrollBarVisibility" Value="Hidden" />
                    <Setter Property="VerticalScrollBarVisibility" Value="Hidden" />
                    <Setter Property="HorizontalScrollMode" Value="Disabled" />
                    <Setter Property="VerticalScrollMode" Value="Disabled" />
                </Style>
            </Grid.Resources>
            <ScrollViewer
                x:Name="LeftScrollViewer"
                Grid.Column="0"
                BorderBrush="SkyBlue"
                BorderThickness="1">
                <TextBlock FontSize="2048" Text="Left" />
            </ScrollViewer>
            <ScrollViewer
                x:Name="RightScrollViewer"
                Grid.Column="1"
                BorderBrush="HotPink"
                BorderThickness="1">
                <TextBlock FontSize="1024" Text="Right" />
            </ScrollViewer>
        </Grid>
        <ScrollBar
            x:Name="VerticalScrollBar"
            Grid.Column="1"
            IndicatorMode="MouseIndicator"
            ValueChanged="VerticalScrollBar_ValueChanged" />
    </Grid>
    
    private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        VerticalScrollBar.ViewportSize = e.NewSize.Height;
        VerticalScrollBar.Maximum = Math.Max(LeftScrollViewer.ScrollableHeight, RightScrollViewer.ScrollableHeight);
    }
    
    private void Grid_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
    {
        double delta = e.GetCurrentPoint(this).Properties.MouseWheelDelta;
        UpdateVerticalScrollBar(delta);
    }
    
    private void Grid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
    {
        double delta = e.Delta.Translation.Y;
        UpdateVerticalScrollBar(delta);
    }
    
    private void UpdateVerticalScrollBar(double delta)
    {
        VerticalScrollBar.Value = Math.Max(0, Math.Min(this.VerticalScrollBar.Maximum, this.VerticalScrollBar.Value - delta));
    }
    
    private void VerticalScrollBar_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
    {
        if (e.NewValue < 0 || e.NewValue > this.VerticalScrollBar.Maximum)
            return;
    
        this.LeftScrollViewer.ScrollToVerticalOffset(e.NewValue);
        this.RightScrollViewer.ScrollToVerticalOffset(e.NewValue);
    }