From 4b503f8b373aba70ee6910562f2531ef63d3d9c8 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 Jun 2020 23:14:46 +0200 Subject: [PATCH] Use EffectiveViewportChanged in ViewportManager. --- .../Repeater/ViewportManager.cs | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/Avalonia.Controls/Repeater/ViewportManager.cs b/src/Avalonia.Controls/Repeater/ViewportManager.cs index b705a518ff..fa85ceec5d 100644 --- a/src/Avalonia.Controls/Repeater/ViewportManager.cs +++ b/src/Avalonia.Controls/Repeater/ViewportManager.cs @@ -49,8 +49,8 @@ namespace Avalonia.Controls // For non-virtualizing layouts, we do not need to keep // updating viewports and invalidating measure often. So when // a non virtualizing layout is used, we stop doing all that work. - bool _managingViewportDisabled; - private IDisposable _effectiveViewportChangedRevoker; + private bool _managingViewportDisabled; + private bool _effectiveViewportChangedSubscribed; private bool _layoutUpdatedSubscribed; public ViewportManager(ItemsRepeater owner) @@ -228,11 +228,15 @@ namespace Avalonia.Controls _pendingViewportShift = default; _unshiftableShift = default; - _effectiveViewportChangedRevoker?.Dispose(); - - if (!_managingViewportDisabled) + if (_managingViewportDisabled && _effectiveViewportChangedSubscribed) { - _effectiveViewportChangedRevoker = SubscribeToEffectiveViewportChanged(_owner); + _owner.EffectiveViewportChanged -= OnEffectiveViewportChanged; + _effectiveViewportChangedSubscribed = false; + } + else if (!_managingViewportDisabled && !_effectiveViewportChangedSubscribed) + { + _owner.EffectiveViewportChanged += OnEffectiveViewportChanged; + _effectiveViewportChangedSubscribed = true; } } @@ -415,15 +419,15 @@ namespace Avalonia.Controls _scroller = null; } - _effectiveViewportChangedRevoker?.Dispose(); - _effectiveViewportChangedRevoker = null; + _owner.EffectiveViewportChanged -= OnEffectiveViewportChanged; + _effectiveViewportChangedSubscribed = false; _ensuredScroller = false; } - private void OnEffectiveViewportChanged(Rect effectiveViewport) + private void OnEffectiveViewportChanged(object sender, EffectiveViewportChangedEventArgs e) { Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "{LayoutId}: EffectiveViewportChanged event callback", _owner.Layout.LayoutId); - UpdateViewport(effectiveViewport); + UpdateViewport(e.EffectiveViewport); _pendingViewportShift = default; _unshiftableShift = default; @@ -468,8 +472,8 @@ namespace Avalonia.Controls } else if (!_managingViewportDisabled) { - _effectiveViewportChangedRevoker?.Dispose(); - _effectiveViewportChangedRevoker = SubscribeToEffectiveViewportChanged(_owner); + _owner.EffectiveViewportChanged += OnEffectiveViewportChanged; + _effectiveViewportChangedSubscribed = true; } _ensuredScroller = true; @@ -541,26 +545,15 @@ namespace Avalonia.Controls // UWP uses the EffectiveViewportChanged event (which I think was implemented specially // for this case): we need to implement that in Avalonia, but the semantics of it aren't // clear to me. Hopefully the source for this event will be released with WinUI 3. - if (control.VisualParent is ScrollContentPresenter scp) + if (control.VisualParent is Layoutable layoutable) { - scp.PreArrange += ScrollContentPresenterPreArrange; - return Disposable.Create(() => scp.PreArrange -= ScrollContentPresenterPreArrange); + layoutable.EffectiveViewportChanged += OnEffectiveViewportChanged; + return Disposable.Create(() => layoutable.EffectiveViewportChanged -= OnEffectiveViewportChanged); } return Disposable.Empty; } - private void ScrollContentPresenterPreArrange(object sender, VectorEventArgs e) - { - var scp = (ScrollContentPresenter)sender; - var effectiveViewport = new Rect((Point)scp.Offset, new Size(e.Vector.X, e.Vector.Y)); - - if (effectiveViewport != _visibleWindow) - { - OnEffectiveViewportChanged(effectiveViewport); - } - } - private class ScrollerInfo { public ScrollerInfo(ScrollViewer scroller)