I have gone through the thread:
binding two VerticalScrollBars one to another
it has almost helped to achieve the goal but still there is something missing.
Well, I made an implementation based on https://www.codeproject.com/Articles/39244/Scroll-Synchronization but it's I think neater.
There's a synchronised scroll token that holds references to the things to scroll. Then there's the attached property that is separate. I haven't figured out how to unregister because the reference remains - so I left that unimplemented.
Eh, here goes:
public class SynchronisedScroll
{
public static SynchronisedScrollToken GetToken(ScrollViewer obj)
{
return (SynchronisedScrollToken)obj.GetValue(TokenProperty);
}
public static void SetToken(ScrollViewer obj, SynchronisedScrollToken value)
{
obj.SetValue(TokenProperty, value);
}
public static readonly DependencyProperty TokenProperty =
DependencyProperty.RegisterAttached("Token", typeof(SynchronisedScrollToken), typeof(SynchronisedScroll), new PropertyMetadata(TokenChanged));
private static void TokenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var scroll = d as ScrollViewer;
var oldToken = e.OldValue as SynchronisedScrollToken;
var newToken = e.NewValue as SynchronisedScrollToken;
if (scroll != null)
{
oldToken?.unregister(scroll);
newToken?.register(scroll);
}
}
}
and the other bit
public class SynchronisedScrollToken
{
List registeredScrolls = new List();
internal void unregister(ScrollViewer scroll)
{
throw new NotImplementedException();
}
internal void register(ScrollViewer scroll)
{
scroll.ScrollChanged += ScrollChanged;
registeredScrolls.Add(scroll);
}
private void ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var sendingScroll = sender as ScrollViewer;
foreach (var potentialScroll in registeredScrolls)
{
if (potentialScroll == sendingScroll)
continue;
if (potentialScroll.VerticalOffset != sendingScroll.VerticalOffset)
potentialScroll.ScrollToVerticalOffset(sendingScroll.VerticalOffset);
if (potentialScroll.HorizontalOffset != sendingScroll.HorizontalOffset)
potentialScroll.ScrollToHorizontalOffset(sendingScroll.HorizontalOffset);
}
}
}
Use by defining a token in some resource accessible to all the things that need to be scroll synchronised.
And then use it wherever you need it by:
I've only tested it when scrolling vertically and it works for me.