How do I synchronize two ScrollViewers?

I have four areas. Three of them are scrolled. I need to sync their movement, so if users move area A (horizontal only) area C simulates movement. If the user moves areaC areaA simulates horizontal and areaB vertical movement.

Since some areas can move 'underneath others, I don't see a way to use one ScrollView:

  • C moves vertically 'under' A
  • C moves horizontally 'under' B
  • B moves vertically "under" the fixed area
  • A moves horizontally "under" the fixed area

The 4 areas

Note that I'm working on a Windows Phone 8.1 app targeting the WinRT runtime (if that current name is missing for it, Silverlight is not.).

About sizes:

  • areaA and areaC have the same width
  • areaB and areaC have the same height

So far I've managed to keep them in sync by subscribing to events ViewChanging

, reading the offset values NextView

from the arg argument, and calling ScrollTo[Vertical,Horizontal]Offset

on the appropriate other scroller. As I said, it works somehow, but they stutter a little pretty . Plus I haven't found a way to mimic the "end of the scroll", so the content is now compressed up / down.

//adding event handler
areaCScroller.ViewChanging += HandleAreaCScrolls;

//handler
void HandleAreaCScrolls(object sender, ScrollViewerViewChangingEventArgs e)
{
    areaAScroller.ScrollToHorizontalOffset(e.NewView.HorizontalOffset);
    areaBScroller.ScrollToVerticalOffset(e.NewView.VerticalOffset);
}

      

I've also tried FinalView values ​​(resulting in StackOverFlowExceptions) and disabling inertia on scrollers (which didn't help, but made them feel less cool).

So my question is, how can I do this better?

I'm not experienced with WPF / XAML, so I could very well miss (or have a low Google foo) control that does what I need. Open to all suggestions (the layout itself is pretty much locked down). I looked here , here and here , but they all do about the same thing that I tried.

+3


source to share


1 answer


I have used ViewChanged from ScrollViewer. Everything worked well for me. Here is the code from MainPage.xaml.cs:

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        var list = new List<int>();
        for (int i = 0; i < 100; ++i)
        {
            list.Add(i);
        }

        ItemsControl1.ItemsSource = list;
        ItemsControl2.ItemsSource = list;
    }

    private void ScrollViewer1_OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        if (ScrollViewer1.VerticalOffset != ScrollViewer2.VerticalOffset)
        {
            ScrollViewer2.ScrollToVerticalOffset(ScrollViewer1.VerticalOffset);
        }
    }

    private void ScrollViewer2_OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        if (ScrollViewer1.VerticalOffset != ScrollViewer2.VerticalOffset)
        {
            ScrollViewer1.ScrollToVerticalOffset(ScrollViewer2.VerticalOffset);
        }
    }

      

And the XAML code from MainPage.xaml



<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="50"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <ScrollViewer Grid.Column="0"
                  x:Name="ScrollViewer1"
                  ViewChanged="ScrollViewer1_OnViewChanged">
        <ItemsControl x:Name="ItemsControl1">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
    <ScrollViewer Grid.Column="2"
                  x:Name="ScrollViewer2"
                  ViewChanged="ScrollViewer2_OnViewChanged">
        <ItemsControl x:Name="ItemsControl2">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>

      

Try this, hope it helps.

+4


source







All Articles