最適解じゃなさそうだけどこんな感じで…。
<Window x:Class="WpfApplication5.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApplication5"mc:Ignorable="d"Title="MainWindow"Height="350"Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition /></Grid.RowDefinitions><Button Content="Dump"Click="ButtonDump_Click" /><ListBox x:Name="ListBox"Grid.Row="1"></ListBox></Grid></Window>
ContainerFromItemで要素がとれなかったらそもそも表示されてない。ContainerFromItemでインスタンスが取れたら、ListBoxからの相対座標がListBoxの矩形領域に収まってたら表示されてるみたいな。
using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace WpfApplication5 { /// <summary>/// MainWindow.xaml の相互作用ロジック/// </summary>publicpartialclass MainWindow : Window { public MainWindow() { InitializeComponent(); this.ListBox.ItemsSource = Enumerable.Range(1, 20) .Select(x => new Person { Name = $"tanaka {x}" }) .ToArray(); } privatevoid ButtonDump_Click(object sender, RoutedEventArgs e) { var box = VisualTreeHelper.GetDescendantBounds(this.ListBox); foreach (var item inthis.ListBox.ItemsSource.Cast<Person>()) { var container = this.ListBox.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem; if (container == null) { Debug.WriteLine($"表示されてない: {item.Name}"); continue; } var top = container.TranslatePoint(new Point(), this.ListBox); if (box.Contains(top)) { Debug.WriteLine($"表示されてる: {item.Name}"); } else { Debug.WriteLine($"表示されてない: {item.Name}"); } } } } publicclass Person { publicstring Name { get; set; } publicoverridestring ToString() { returnthis.Name; } } }
でも、Padding指定されたら破たんするかな…。