So I need to synchronise two ScrollViewers that are on different Windows. I have an Attached Property that enables me to scroll each ScrollViewer using buttons instead of the Scroll Bar and have tried to use that to do the synchronisation, adapting code I found here that was for UWP
Synchronized scrolling of two ScrollViewers whenever any one is scrolled in wpf
Like so.....
public class AutoScrollBehavior : Behavior<ScrollViewer>
{
private double _height = 0.0d;
private ScrollViewer _scrollViewer = null;
protected override void OnAttached()
{
base.OnAttached();
this._scrollViewer = base.AssociatedObject;
this._scrollViewer.LayoutUpdated += new EventHandler(_scrollViewer_LayoutUpdated);
var source = GetSource(this.AssociatedObject);
this.UpdateTargetViewAccordingToSource(source);
}
private void _scrollViewer_LayoutUpdated(object sender, EventArgs e)
{
if (Math.Abs(this._scrollViewer.ExtentHeight - _height) > 1)
{
this._scrollViewer.ScrollToVerticalOffset(this._scrollViewer.ExtentHeight);
this._height = this._scrollViewer.ExtentHeight;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (this._scrollViewer != null)
{
this._scrollViewer.LayoutUpdated -= new EventHandler(_scrollViewer_LayoutUpdated);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
public static ScrollViewer GetSource(DependencyObject obj)
{
return (ScrollViewer)obj.GetValue(SourceProperty);
}
public static void SetSource(DependencyObject obj, ScrollViewer value)
{
obj.SetValue(SourceProperty, value);
}
public static readonly DependencyProperty SourceProperty =
DependencyProperty.RegisterAttached("Source", typeof(object), typeof(AutoScrollBehavior), new PropertyMetadata(null, SourceChangedCallBack));
private static void SourceChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AutoScrollBehavior synchronizeHorizontalOffsetBehavior = d as AutoScrollBehavior;
if (synchronizeHorizontalOffsetBehavior != null)
{
var oldSourceScrollViewer = e.OldValue as ScrollViewer;
var newSourceScrollViewer = e.NewValue as ScrollViewer;
if (oldSourceScrollViewer != null)
{
oldSourceScrollViewer.SourceUpdated -= synchronizeHorizontalOffsetBehavior.SourceScrollViewer_ViewChanged;
}
if (newSourceScrollViewer != null)
{
newSourceScrollViewer.SourceUpdated += synchronizeHorizontalOffsetBehavior.SourceScrollViewer_ViewChanged;
synchronizeHorizontalOffsetBehavior.UpdateTargetViewAccordingToSource(newSourceScrollViewer);
}
}
}
private void SourceScrollViewer_ViewChanged(object sender, DataTransferEventArgs e)
{
ScrollViewer sourceScrollViewer = sender as ScrollViewer;
this.UpdateTargetViewAccordingToSource(sourceScrollViewer);
}
private void UpdateTargetViewAccordingToSource(ScrollViewer sourceScrollViewer)
{
if (sourceScrollViewer != null)
{
if (this.AssociatedObject != null)
{
this.AssociatedObject.ScrollToHorizontalOffset(sourceScrollViewer.HorizontalOffset);// .ChangeView(sourceScrollViewer.HorizontalOffset, null, null);
}
}
}
}
Usage...
<ScrollViewer
HorizontalScrollMode="Enabled"
HorizontalScrollBarVisibility="Hidden">
<interactivity:Interaction.Behaviors>
<behaviors:SynchronizeHorizontalOffsetBehavior Source="{Binding ElementName=ScrollViewer}" />
</interactivity:Interaction.Behaviors>
</ScrollViewer>
<ScrollViewer x:Name="ScrollViewer" />
But that hasn't worked, maybe I have not converted the UPW code correctly... here is my Attached Property as is. Would like a solution that is similar to the UWP solution is the link above.
public class AutoScrollBehavior : Behavior<ScrollViewer>
{
private double _height = 0.0d;
private ScrollViewer _scrollViewer = null;
protected override void OnAttached()
{
base.OnAttached();
this._scrollViewer = base.AssociatedObject;
this._scrollViewer.LayoutUpdated += new EventHandler(_scrollViewer_LayoutUpdated);
}
private void _scrollViewer_LayoutUpdated(object sender, EventArgs e)
{
if (Math.Abs(this._scrollViewer.ExtentHeight - _height) > 1)
{
this._scrollViewer.ScrollToVerticalOffset(this._scrollViewer.ExtentHeight);
this._height = this._scrollViewer.ExtentHeight;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (this._scrollViewer != null)
{
this._scrollViewer.LayoutUpdated -= new EventHandler(_scrollViewer_LayoutUpdated);
}
}
}
Any MVVM ideas would be useful...