diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs index 381080ce4a..f9b383a928 100644 --- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs +++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs @@ -7,6 +7,7 @@ using System.Collections.Specialized; using System.Linq; using Avalonia.Controls.Utils; using Avalonia.Input; +using Avalonia.Layout; using Avalonia.Utilities; namespace Avalonia.Controls.Presenters @@ -210,7 +211,19 @@ namespace Avalonia.Controls.Presenters InvalidateScroll(); } - return generator.ContainerFromIndex(newItemIndex); + var container = generator.ContainerFromIndex(newItemIndex); + + // We need to do a layout here because it's possible that the container we moved to + // is only partially visible due to differing item sizes. If the container is only + // partially visible, scroll again. + LayoutManager.Instance?.ExecuteLayoutPass(); + + if (!new Rect(panel.Bounds.Size).Contains(container.Bounds)) + { + OffsetValue += newItemIndex > itemIndex ? 1 : -1; + } + + return container; } return null; diff --git a/src/Avalonia.SceneGraph/Rect.cs b/src/Avalonia.SceneGraph/Rect.cs index de4d13890b..10253ec829 100644 --- a/src/Avalonia.SceneGraph/Rect.cs +++ b/src/Avalonia.SceneGraph/Rect.cs @@ -224,14 +224,24 @@ namespace Avalonia } /// - /// Determines whether a points in in the bounds of the rectangle. + /// Determines whether a point in in the bounds of the rectangle. /// /// The point. /// true if the point is in the bounds of the rectangle; otherwise false. public bool Contains(Point p) { - return p.X >= _x && p.X < _x + _width && - p.Y >= _y && p.Y < _y + _height; + return p.X >= _x && p.X <= _x + _width && + p.Y >= _y && p.Y <= _y + _height; + } + + /// + /// Determines whether the rectangle fully contains another rectangle. + /// + /// The rectangle. + /// true if the rectangle is fully contained; otherwise false. + public bool Contains(Rect r) + { + return Contains(r.TopLeft) && Contains(r.BottomRight); } ///