Synchronized scrolling of two ScrollViewers whenever any one is scrolled in wpf

前端 未结 5 1756
长情又很酷
长情又很酷 2020-11-27 05:48

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.

5条回答
  •  爱一瞬间的悲伤
    2020-11-27 06:24

    If it can be useful, here's a behavior (for UWP, but it's enough to get the idea); using a behavior helps to decouple view and code in a MVVM design.

    using Microsoft.Xaml.Interactivity;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    public class SynchronizeHorizontalOffsetBehavior : Behavior
    {
        public static ScrollViewer GetSource(DependencyObject obj)
        {
            return (ScrollViewer)obj.GetValue(SourceProperty);
        }
    
        public static void SetSource(DependencyObject obj, ScrollViewer value)
        {
            obj.SetValue(SourceProperty, value);
        }
    
        // Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.RegisterAttached("Source", typeof(object), typeof(SynchronizeHorizontalOffsetBehavior), new PropertyMetadata(null, SourceChangedCallBack));
    
        private static void SourceChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SynchronizeHorizontalOffsetBehavior synchronizeHorizontalOffsetBehavior = d as SynchronizeHorizontalOffsetBehavior;
            if (synchronizeHorizontalOffsetBehavior != null)
            {
                var oldSourceScrollViewer = e.OldValue as ScrollViewer;
                var newSourceScrollViewer = e.NewValue as ScrollViewer;
                if (oldSourceScrollViewer != null)
                {
                    oldSourceScrollViewer.ViewChanged -= synchronizeHorizontalOffsetBehavior.SourceScrollViewer_ViewChanged;
                }
                if (newSourceScrollViewer != null)
                {
                    newSourceScrollViewer.ViewChanged += synchronizeHorizontalOffsetBehavior.SourceScrollViewer_ViewChanged;
                    synchronizeHorizontalOffsetBehavior.UpdateTargetViewAccordingToSource(newSourceScrollViewer);
                }
            }
        }
    
        private void SourceScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
        {
            ScrollViewer sourceScrollViewer = sender as ScrollViewer;
            this.UpdateTargetViewAccordingToSource(sourceScrollViewer);
        }
    
        private void UpdateTargetViewAccordingToSource(ScrollViewer sourceScrollViewer)
        {
            if (sourceScrollViewer != null)
            {
                if (this.AssociatedObject != null)
                {
                    this.AssociatedObject.ChangeView(sourceScrollViewer.HorizontalOffset, null, null);
                }
            }
        }
    
        protected override void OnAttached()
        {
            base.OnAttached();
            var source = GetSource(this.AssociatedObject);
            this.UpdateTargetViewAccordingToSource(source);
        }
    }
    

    Here's how to use it:

    
               
                  
                                                      
    
    
    

提交回复
热议问题