Я вроде как-то решил. Я нашел это: http://munnaondotnet.blogspot.com/2011/09/is-item-is-visible-in-scroll-viewer.html
тогда я только что отредактировал немного xaml
<ListBox.Template>
<ControlTemplate>
<ScrollViewer x:Name="ScrollViewer1" ScrollChanged="HandleScrollChanged"
CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<Grid x:Name="GridRoot" Width="250" Height="460" Background="Red" >
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Visibility" Value="Collapsed"/>
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.8" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
и код позади
private void HandleScrollChanged(object sender, ScrollChangedEventArgs e)
{
ShowVisibleItems(sender);
}
private void ShowVisibleItems(object sender)
{
var scrollViewer = (FrameworkElement)sender;
foreach (var item in this.ListBox1.Items)
{
var listBoxItem = (FrameworkElement)this.ListBox1.ItemContainerGenerator.ContainerFromItem(item);
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(listBoxItem);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
Grid target = (Grid)myDataTemplate.FindName("GridRoot", myContentPresenter);
if (IsFullyOrPartiallyVisible(listBoxItem, scrollViewer))
{
target.Visibility = Visibility.Visible;
}
else
{
target.Visibility = Visibility.Collapsed;
}
}
}
private bool IsFullyOrPartiallyVisible(FrameworkElement element, FrameworkElement container)
{
if (element == null || container == null)
return false;
if (element.Visibility != Visibility.Visible)
return false;
Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}