1

I need advice. How can I create an animation of items in the ListBox with scrolling, see the picture. I need to achieve the same animation when using WrapPanel. I will be glad for any advice.

animated fade when scrolling animated fade when scrolling

Here's the code

 <!--VirtualizingStackPanel.IsVirtualizing="True"
    VirtualizingStackPanel.CacheLengthUnit="Pixel"
    VirtualizingStackPanel.CacheLength="100,100"
    VirtualizingStackPanel.ScrollUnit="Pixel"
    VirtualizingStackPanel.VirtualizationMode="Recycling"-->

    <ListBox x:Name="ListBox1" ItemsSource="{Binding MoviesCvs.View,IsAsync=True}" 
             Style="{StaticResource CommonListBoxStyle}"
             HorizontalContentAlignment="Stretch"
             IsSynchronizedWithCurrentItem="False"
             ScrollViewer.CanContentScroll="True"
             ScrollViewer.VerticalScrollBarVisibility="Auto"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <!--<VirtualizingStackPanel IsItemsHost="True"/>-->
                <WrapPanel Orientation="Vertical" IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Margin="0"  Background="Transparent"  Height="460" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}">
                    <Grid Background="Transparent" HorizontalAlignment="Left" Width="250" Height="460" Margin="0">
                        <StackPanel VerticalAlignment="Top">
                            <cachedImage:Image Stretch="Uniform" ImageUrl="{Binding PosterPath}" >
                                <cachedImage:Image.Triggers>
                                    <!-- Opacity animation -->
                                    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.8" />
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </cachedImage:Image.Triggers>
                                  <!-- ********************** -->
                            </cachedImage:Image>
                            <TextBlock Margin="5,10,5,0" Text="{Binding MovieTitle}" TextTrimming="CharacterEllipsis" Foreground="Black" TextWrapping="Wrap" MaxHeight="50" FontSize="17"/>
                        </StackPanel>
                    </Grid>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Download source code

4
  • What is not working with your current code? Commented Oct 22, 2019 at 16:57
  • Try to trigger on the ScrollViewer.ScrollChanged Event. Commented Oct 22, 2019 at 17:13
  • Even if they do, they probably don't want to re-trigger the animation everytime the scroll changes by 1 unit. Though this is a good starting point I guess. Commented Oct 22, 2019 at 17:18
  • @CorentinPane Why not? As long as there is virtualization enabled this shouldn't be a performance issue. The animation starts from a low opacity value and increases to one as soon as the scrolling stops. Each scroll will reset the opacity to the low value. The effect should be exactly the same as shown in the example gif image. Commented Oct 22, 2019 at 19:45

1 Answer 1

2

I sort of solved it somehow. I found this : http://munnaondotnet.blogspot.com/2011/09/is-item-is-visible-in-scroll-viewer.html

then i just edited a little 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>

and code behind

  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);
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.