diff --git a/VirtualListView/Controls/VirtualListView.cs b/VirtualListView/Controls/VirtualListView.cs index 35e917c..cb890bf 100644 --- a/VirtualListView/Controls/VirtualListView.cs +++ b/VirtualListView/Controls/VirtualListView.cs @@ -402,4 +402,12 @@ public void ViewAttached(PositionInfo position, IView view) void RaiseSelectedItemsChanged(ItemPosition[] previousSelection, ItemPosition[] newSelection) => this.OnSelectedItemsChanged?.Invoke(this, new SelectedItemsChangedEventArgs(previousSelection, newSelection)); + public IReadOnlyList FindVisiblePositions() + { +#if ANDROID || IOS || MACCATALYST || WINDOWS + if (Handler is IVirtualListViewHandler handler) + return handler.FindVisiblePositions(); +#endif + return []; + } } diff --git a/VirtualListView/IVirtualListViewHandler.cs b/VirtualListView/IVirtualListViewHandler.cs new file mode 100644 index 0000000..a67e9b0 --- /dev/null +++ b/VirtualListView/IVirtualListViewHandler.cs @@ -0,0 +1,8 @@ +namespace Microsoft.Maui; + +public interface IVirtualListViewHandler +{ +#if ANDROID || IOS || MACCATALYST || WINDOWS + IReadOnlyList FindVisiblePositions(); +#endif +} diff --git a/VirtualListView/Platforms/Windows/VirtualListViewHandler.windows.cs b/VirtualListView/Platforms/Windows/VirtualListViewHandler.windows.cs index 9c0d766..86e1be6 100644 --- a/VirtualListView/Platforms/Windows/VirtualListViewHandler.windows.cs +++ b/VirtualListView/Platforms/Windows/VirtualListViewHandler.windows.cs @@ -5,8 +5,10 @@ using WVisibility = Microsoft.UI.Xaml.Visibility; using WFrameworkElement = Microsoft.UI.Xaml.FrameworkElement; using WScrollBarVisibility = Microsoft.UI.Xaml.Controls.ScrollBarVisibility; +using WRect = Windows.Foundation.Rect; using Microsoft.Maui.Platform; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; namespace Microsoft.Maui; @@ -187,4 +189,37 @@ void UpdateHorizontalScrollbarVisibility(ScrollBarVisibility scrollBarVisibility _ => WScrollBarVisibility.Auto }; } + + public IReadOnlyList FindVisiblePositions() + { + var positions = new List(); + + // This gets us all the direct children of our repeater which should be IrElementContainers + // The items will not all be visible, since virtualizing causes items to get setup out of view + // before being displayed. We need to check if they are actually visible. + var childrenCount = VisualTreeHelper.GetChildrenCount(itemsRepeater); + + for (int i = 0; i < childrenCount; i++) + { + // See if the child is an IrElementContainer + if (VisualTreeHelper.GetChild(itemsRepeater, i) is IrElementContainer irElementContainer) + { + // Is the item actually visible? + if (VisibilityHitTest(irElementContainer, itemsRepeater)) + positions.Add(irElementContainer.PositionInfo); + } + } + + return positions; + } + + static bool VisibilityHitTest(IrElementContainer element, FrameworkElement container) + { + var bounds = element.TransformToVisual(container).TransformBounds(new WRect(0.0, 0.0, element.ActualWidth, element.ActualHeight)); + + return bounds.Left < container.ActualWidth + && bounds.Top < container.ActualHeight + && bounds.Right > 0 + && bounds.Bottom > 0; + } } diff --git a/VirtualListView/VirtualListViewHandler.cs b/VirtualListView/VirtualListViewHandler.cs index 6ea1977..79cf0bd 100644 --- a/VirtualListView/VirtualListViewHandler.cs +++ b/VirtualListView/VirtualListViewHandler.cs @@ -2,7 +2,7 @@ namespace Microsoft.Maui; -public partial class VirtualListViewHandler +public partial class VirtualListViewHandler : IVirtualListViewHandler { #if ANDROID || IOS || MACCATALYST || WINDOWS public static new IPropertyMapper ViewMapper = new PropertyMapper(Handlers.ViewHandler.ViewMapper)