动画插入到ItemsControl

10

有时我觉得WPF很难理解。在给定的XAML中,如何为添加到ObservableCollection Timeline的新项添加触发器以进行动画(向下滑动,淡入)。我看过各种列表框的示例,但没有针对项目控件的。

<Grid>
    <ScrollViewer>
        <ItemsControl Name="TimelineItem"
                      ItemsSource="{Binding Timeline}"
                      Style="{StaticResource TimelineStyle}"
                      ItemContainerStyle="{StaticResource TweetItemStyle}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid VerticalAlignment="Top"
                          HorizontalAlignment="Left">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Style="{StaticResource TweetImageColumnStyle}" />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Rectangle Grid.Column="0"
                                   Style="{StaticResource TweetImageStyle}">
                            <Rectangle.Fill>
                                <ImageBrush ImageSource="{Binding ProfileImageUrl}" />
                            </Rectangle.Fill>
                        </Rectangle>
                        <StackPanel Grid.Column="1">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0"
                                           Style="{StaticResource TweetNameStyle}"
                                           Text="{Binding Name}" />
                                <TextBlock Grid.Column="1"
                                           Style="{StaticResource TweetTimeStyle}"
                                           Text="{Binding TimeAgo}" />
                            </Grid>
                            <Controls:TextBlockMarkup Grid.Row="1"
                                                      Grid.Column="1"
                                                      Markup="{Binding MarkupText}"
                                                      Style="{StaticResource TweetStyle}" />
                        </StackPanel>
                        <Separator Grid.Row="2"
                                   Grid.ColumnSpan="2"
                                   Style="{StaticResource TweetSeparatorTop}" />
                        <Separator Grid.Row="3"
                                   Grid.ColumnSpan="2"
                                   Style="{StaticResource TweetSeparatorBottom}" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>

一个好的参考文章:https://asimplify.com/wpf-itemscontrol-animation-insert-asimplify/ - Khawaja Asim
1个回答

23

我已经有一段时间没有使用WPF进行动画制作了,但是这应该可以通过在ItemsControlDataTemplate中设置一个 DataTrigger 来实现 Loaded 事件。

需要注意以下几点:

  1. 将下面的XAML添加到 ItemsControl 的 DataTemplate 中。
  2. 给 DataTemplate 内部的 <Grid> 命名为 "MyGrid"。
  3. 将 RenderTransformOrigin 属性添加到 MyGrid 上以将 Y 轴原点设置在顶部:
    • <Grid x:Name="MyGrid" RenderTransformOrigin="0.5,0">
  4. 确保在网格中包含 Grid.RenderTransform 附加属性 (请参见下面的示例)

Xaml

<DataTemplate.Resources>
    <Storyboard x:Key="ItemAnimation" AutoReverse="False">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyGrid" Storyboard.TargetProperty="(UIElement.Opacity)">
            <EasingDoubleKeyFrame KeyTime="0" Value="0" />
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyGrid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
            <EasingDoubleKeyFrame KeyTime="0" Value="0" />
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</DataTemplate.Resources>

<DataTemplate.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource ItemAnimation}" />
    </EventTrigger>
</DataTemplate.Triggers>

将RenderTransform组添加到您的Grid中

<!-- Include in the Grid -->
<Grid.RenderTransform>
    <TransformGroup>
        <ScaleTransform/>
    </TransformGroup>
</Grid.RenderTransform>

这应该足够接近,以便您可以自定义它。值得一提的是:我使用Blend通过编辑Timeline对象的ItemTemplate样式来构建动画。

最后一个注意点:当窗口首次加载原始集合的每个项时,动画将发生。当将单个项目添加到集合中时,也会发生动画。这种行为有点奇怪,因此您可以在xaml中删除触发器的显式绑定,并在ItemsControl或Window加载后在代码后台绑定触发器。

编辑

  1. 我已更新示例,使其现在可以与您的XAML一起使用。
  2. 添加了另一个动画来滑动(在某种程度上)新项目。实际上,它从Y轴顶部开始,从0%的大小增长到100%。
  3. 修改了上述注意事项#3,包括一个RenderTransformOrigin属性。
  4. 添加了注意事项#4,包括Grid.RenderTransform附加属性。

非常好的答案。不透明度效果很棒,但是我在使用slidedown时遇到了一个错误。'[Unknown]'属性在路径'(0).(1)[3].(2)'中没有指向DependencyObject。我尝试了不同的子索引,但我不太确定如何解释这个错误。 - Mike Ward
看起来我需要一个变换组来使高度动画工作。我通过添加以下内容使其有点工作: 你觉得呢? - Mike Ward
1
很遗憾,效果并不是我所希望的。内容“增长”,但空间(插入项的高度)已经设置为完整高度。内容会增长到分配的高度。我真正希望的是高度能够改变。我试过动画化高度,但布局变得混乱了。在CSS中,我可以轻松地动画化高度。但在WPF中好像不可能。 - Mike Ward
1
@MikeWard 我知道这个问题很旧,但是你还记得你用什么来使项目高度动画化吗? - SapuSeven
@SapuSeven 我从来没有搞定高度问题。我只是将整个列表向下滑动并使用了淡入效果。不是我想要的,但这是我能做到的最接近的方式。 - Mike Ward
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接