To support touch operations, we can't disable HorizontalScrollMode and VerticalScrollMode.
The following seems to work. Can you give it a try?
<Grid ColumnDefinitions="*,Auto">
<Grid
Grid.Column="0"
ColumnDefinitions="*,*"
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"
ViewChanged="LeftScrollViewer_ViewChanged">
<TextBlock FontSize="2048" Text="Left" />
</ScrollViewer>
<ScrollViewer
x:Name="RightScrollViewer"
Grid.Column="1"
ViewChanged="RightScrollViewer_ViewChanged">
<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)
{
VerticalScrollBar.Value = Math.Max(0, Math.Min(this.VerticalScrollBar.Maximum, this.VerticalScrollBar.Value - e.GetCurrentPoint(this).Properties.MouseWheelDelta));
}
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);
}
private void LeftScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (sender is not ScrollViewer scrollViewer)
return;
VerticalScrollBar.Value = scrollViewer.VerticalOffset;
}
private void RightScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (sender is not ScrollViewer scrollViewer)
return;
VerticalScrollBar.Value = scrollViewer.VerticalOffset;
}