同步两个ScrollViewers

时间:2018-04-07 13:34:37

标签: c# wpf mvvm

所以我需要同步两个不同Windows上的ScrollViewer。我有一个附加属性,使我能够使用按钮而不是滚动条滚动每个ScrollViewer,并尝试使用它来进行同步,调整我在这里找到的用于UWP的代码

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

喜欢这样......

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);
            }
        }
    }
}

...用法

<ScrollViewer
      HorizontalScrollMode="Enabled"
      HorizontalScrollBarVisibility="Hidden">
          <interactivity:Interaction.Behaviors>
          <behaviors:SynchronizeHorizontalOffsetBehavior Source="{Binding ElementName=ScrollViewer}" />
       </interactivity:Interaction.Behaviors>                                       
</ScrollViewer>
<ScrollViewer x:Name="ScrollViewer" />

但那还没有奏效,也许我没有正确转换UPW代码......这是我的附属财产。希望与UWP解决方案类似的解决方案是上面的链接。

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);
        }
    }
}

任何MVVM想法都会有用......

1 个答案:

答案 0 :(得分:1)

订阅Window1事件并匹配滚动条的偏移量。在下面的示例中,ScrollViewer Window2将滚动ScrollViewer <ScrollViewer Name="W1ScrollViewer" ScrollChanged="W1ScrollViewer_ScrollChanged/>

Window 1 XAML:

<ScrollViewer Name="W2ScrollViewer"/>

Window 2 XAML:

 //Create an object to store Window2 in
 private Window2 window2; 

 //Pass Window2 into the Window1 constructor.
 public Window1(Window2 w)
 {
    window2 = w;
    InitializeComponent();
 }

 //Scroll Window2's ScrollViewer as on Window1's ScrollViewer ScrollChanged
 private void W1ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
 {
      window2.W2ScrollViewer.ScrollToVerticalOffset(e.VerticalOffset);
      window2.W2ScrollViewer.ScrollToHorizontalOffset(e.HorizontalOffset);
 }

Window 1 Code:

newdata = df[df['Address'].str[0] == 'N'] # filtering the dataframe 
print (newdata)
  Address  Age  YrsOfEducation  name
0      NY   23              10  john
1      NJ   32              15   tom
3      NY   42              12  rock

这只是一个简单的例子。您可能需要找到一种不同的方式来在视图之间传递窗口,但这应该让您朝着正确的方向前进。