两个ScrollViewers同步滚动,只要在wpf中滚动任何一个

Vik*_*am_ 16 .net c# wpf scrollviewer

我已经完成了这个帖子:

将两个VerticalScrollBar绑定到另一个

它几乎有助于实现目标,但仍然缺少一些东西.这是左右或上下移动滚动条给出了我的两个滚动查看器中滚动的预期行为,但是当我们尝试在滚动查看器中滚动使用/单击这些滚动条末端的箭头按钮时,只滚动一个滚动查看器预期的行为.

那么我们需要添加/编辑以解决这个问题呢?

Eir*_*rik 37

一种方法是使用ScrollChanged事件来更新另一个ScrollViewer

<ScrollViewer Name="sv1" Height="100" 
              HorizontalScrollBarVisibility="Auto"
              ScrollChanged="ScrollChanged">
    <Grid Height="1000" Width="1000" Background="Green" />
</ScrollViewer>

<ScrollViewer Name="sv2" Height="100" 
              HorizontalScrollBarVisibility="Auto"
              ScrollChanged="ScrollChanged">
    <Grid Height="1000" Width="1000" Background="Blue" />
</ScrollViewer>

private void ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (sender == sv1)
        {
            sv2.ScrollToVerticalOffset(e.VerticalOffset);
            sv2.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
        else
        {
            sv1.ScrollToVerticalOffset(e.VerticalOffset);
            sv1.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 我不得不添加`if(e.VerticalChange == 0 && e.Horizo​​ntalChange == 0){return; 因为其他时候调用了这个事件处理程序(即视口大小改变,范围),所以为了避免它们不断重置为0. (5认同)

Ren*_*ers 7

问题出在WPF上,但是如果任何开发UWP的人都会遇到这种情况,我不得不采取略微不同的方法.
在UWP中,当您设置另一个滚动查看器的滚动偏移量(使用ScrollViewer.ChangeView)时,它还会在另一个滚动查看器上触发ViewChanged事件,基本上会创建一个循环,导致它非常麻烦,并且无法正常工作.

如果正在滚动的对象不等于处理事件的最后一个对象,我通过在处理事件时使用一点时间来解决这个问题.

XAML:

<ScrollViewer x:Name="ScrollViewer1" ViewChanged="SynchronizedScrollerOnViewChanged"> ... </ScrollViewer>
<ScrollViewer x:Name="ScrollViewer2" ViewChanged="SynchronizedScrollerOnViewChanged"> ... </ScrollViewer>
Run Code Online (Sandbox Code Playgroud)

代码背后:

public sealed partial class MainPage
{
    private const int ScrollLoopbackTimeout = 500;

    private object _lastScrollingElement;
    private int _lastScrollChange = Environment.TickCount;

    public SongMixerUserControl()
    {
        InitializeComponent();
    }

    private void SynchronizedScrollerOnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        if (_lastScrollingElement != sender && Environment.TickCount - _lastScrollChange < ScrollLoopbackTimeout) return;

        _lastScrollingElement = sender;
        _lastScrollChange = Environment.TickCount;

        ScrollViewer sourceScrollViewer;
        ScrollViewer targetScrollViewer;
        if (sender == ScrollViewer1)
        {
            sourceScrollViewer = ScrollViewer1;
            targetScrollViewer = ScrollViewer2;
        }
        else
        {
            sourceScrollViewer = ScrollViewer2;
            targetScrollViewer = ScrollViewer1;
        }

        targetScrollViewer.ChangeView(null, sourceScrollViewer.VerticalOffset, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,超时为500毫秒.这可能看起来有点长,但是当UWP应用程序在滚动时(在鼠标上使用滚轮时)有动画(或者,实际上是宽松的),它会导致事件在几百毫秒内触发几次.这个超时似乎完美无缺.

  • Bravo Mate!与我的UWP完美配合,我在WPF问题下找到答案.荣誉 (2认同)